Package net.tomp2p.rpc

Source Code of net.tomp2p.rpc.DirectDataRPC

/*
* Copyright 2009 Thomas Bocek
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package net.tomp2p.rpc;

import io.netty.buffer.Unpooled;

import java.io.IOException;

import net.tomp2p.connection.ChannelCreator;
import net.tomp2p.connection.ConnectionBean;
import net.tomp2p.connection.PeerBean;
import net.tomp2p.connection.PeerConnection;
import net.tomp2p.connection.RequestHandler;
import net.tomp2p.connection.Responder;
import net.tomp2p.futures.FutureResponse;
import net.tomp2p.message.Buffer;
import net.tomp2p.message.Message;
import net.tomp2p.message.Message.Type;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.utils.Utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DirectDataRPC extends DispatchHandler {
    private static final Logger LOG = LoggerFactory.getLogger(DirectDataRPC.class);

    private volatile RawDataReply rawDataReply;

    private volatile ObjectDataReply objectDataReply;

    public DirectDataRPC(PeerBean peerBean, ConnectionBean connectionBean) {
        super(peerBean, connectionBean);
        register(RPC.Commands.DIRECT_DATA.getNr());
    }

    /**
     * Send data directly to a peer. Make sure you have set up a reply handler. This is an RPC.
     *
     * @param remotePeer
     *            The remote peer to store the data
     * @param buffer
     *            The data to send to the remote peer
     * @param raw
     *            Set to true if a the byte array is expected or if it should be converted to an object
     * @param channelCreator
     *            The channel creator
     * @param idleTCPMillis
     *            Set the timeout when a connection is considered inactive (idle)
     * @param forceUDP
     *            Set to true if the communication should be UDP, default is TCP
     * @return FutureResponse that stores which content keys have been stored.
     */

    public RequestHandler<FutureResponse> sendInternal(final PeerAddress remotePeer,
            final SendDirectBuilderI sendDirectBuilder) {
        final Message message = createMessage(remotePeer, RPC.Commands.DIRECT_DATA.getNr(),
                sendDirectBuilder.isRaw() ? Type.REQUEST_1 : Type.REQUEST_2);
        final FutureResponse futureResponse = new FutureResponse(message,
                sendDirectBuilder.progressListener());

        if (sendDirectBuilder.isSign()) {
            message.publicKeyAndSign(sendDirectBuilder.keyPair());
        }
        message.streaming(sendDirectBuilder.isStreaming());

        if (sendDirectBuilder.isRaw()) {
            message.buffer(sendDirectBuilder.buffer());
        } else {
            byte[] me;
            try {
                me = Utils.encodeJavaObject(sendDirectBuilder.object());
                message.buffer(new Buffer(Unpooled.wrappedBuffer(me)));
            } catch (IOException e) {
                futureResponse.failed("cannot convert object", e);
            }      
        }

        return new RequestHandler<FutureResponse>(futureResponse, peerBean(), connectionBean(),
                sendDirectBuilder);
    }

    public FutureResponse send(final PeerAddress remotePeer, final SendDirectBuilderI sendDirectBuilder,
            final ChannelCreator channelCreator) {
        final RequestHandler<FutureResponse> requestHandler = sendInternal(remotePeer, sendDirectBuilder);
        if (!sendDirectBuilder.isForceUDP()) {
            return requestHandler.sendTCP(channelCreator);
        } else {
            return requestHandler.sendUDP(channelCreator);
        }
    }

    public void rawDataReply(final RawDataReply rawDataReply) {
        this.rawDataReply = rawDataReply;
    }

    public void objectDataReply(ObjectDataReply objectDataReply) {
        this.objectDataReply = objectDataReply;
    }

    public boolean hasRawDataReply() {
        return rawDataReply != null;
    }

    public boolean hasObjectDataReply() {
        return objectDataReply != null;
    }

    @Override
    public void handleResponse(final Message message, PeerConnection peerConnection, final boolean sign, Responder responder) throws Exception {
        if (!((message.type() == Type.REQUEST_1 || message.type() == Type.REQUEST_2) && message
                .command() == RPC.Commands.DIRECT_DATA.getNr())) {
            throw new IllegalArgumentException("Message content is wrong");
        }
        final Message responseMessage = createResponseMessage(message, Type.OK);

        if (sign) {
            responseMessage.publicKeyAndSign(peerBean().getKeyPair());
        }
        final RawDataReply rawDataReply2 = rawDataReply;
        final ObjectDataReply objectDataReply2 = objectDataReply;
        if (message.type() == Type.REQUEST_1 && rawDataReply2 == null) {
            responseMessage.type(Type.NOT_FOUND);
        } else if (message.type() == Type.REQUEST_2 && objectDataReply2 == null) {
            responseMessage.type(Type.NOT_FOUND);
        } else {
            final Buffer requestBuffer = message.buffer(0);
            // the user can reply with null, indicating not found. Or
            // returning the request buffer, which means nothing is
            // returned. Or an exception can be thrown
            if (message.type() == Type.REQUEST_1) {
                LOG.debug("handling request1");
                final Buffer replyBuffer = rawDataReply2.reply(message.sender(), requestBuffer,
                        message.isDone());
                if (replyBuffer == null && message.isDone()) {
                    responseMessage.type(Type.NOT_FOUND);
                } else if (replyBuffer != requestBuffer) {
                    // can be partial as well
                    if (!replyBuffer.isComplete()) {
                        responseMessage.streaming();
                    }
                    responseMessage.buffer(replyBuffer);
                }
            } else { // no streaming here when we deal with objects
                Object obj = Utils.decodeJavaObject(requestBuffer.buffer());
                LOG.debug("handling {}", obj);

                Object reply = objectDataReply2.reply(message.sender(), obj);
                if (reply == null) {
                    responseMessage.type(Type.NOT_FOUND);
                } else if (reply == obj) {
                    responseMessage.type(Type.OK);
                } else {
                    byte[] me = Utils.encodeJavaObject(reply);
                    responseMessage.buffer(new Buffer(Unpooled.wrappedBuffer(me)));
                }
            }
        }
        responder.response(responseMessage);
    }
}
TOP

Related Classes of net.tomp2p.rpc.DirectDataRPC

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.