/* * 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 net.tomp2p.connection2.ConnectionBean; import net.tomp2p.connection2.PeerBean; import net.tomp2p.message.Message2; import net.tomp2p.message.Message2.Type; import net.tomp2p.peers.PeerAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The dispatcher handlers that can be added to the Dispatcher. * * @author Thomas Bocek * */ public abstract class DispatchHandler { private static final Logger LOG = LoggerFactory.getLogger(DispatchHandler.class); private final PeerBean peerBean; private final ConnectionBean connectionBean; private boolean sign = false; /** * Creates a handler with a connection and peer bean. * * @param peerBean * The peer bean * @param connectionBean * The connection bean * @param names * The command names */ public DispatchHandler(final PeerBean peerBean, final ConnectionBean connectionBean, final int... names) { this.peerBean = peerBean; this.connectionBean = connectionBean; connectionBean.dispatcher().registerIoHandler(peerBean.serverPeerAddress().getPeerId(), this, names); } /** * @param sign * Set to true if message is signed */ public void sign(final boolean sign) { this.sign = sign; } /** * @return The peer bean */ public PeerBean peerBean() { return peerBean; } /** * @return The connection bean */ public ConnectionBean connectionBean() { return connectionBean; } /** * Create a request message and fills it with connection bean and peer bean parameters. * * @param recipient * The recipient of this message * @param name * The commend type * @param type * The request type * @return The request message */ public Message2 createMessage(final PeerAddress recipient, final byte name, final Type type) { return new Message2().setRecipient(recipient).setSender(peerBean().serverPeerAddress()) .setCommand(name).setType(type).setVersion(connectionBean().p2pId()); } /** * Create a response message and fills it with connection bean and peer bean parameters. * * @param requestMessage * The request message * @param replyType * The type of the reply * @return The reply message */ public Message2 createResponseMessage(final Message2 requestMessage, final Type replyType) { Message2 replyMessage = new Message2(); // this will have the ports > 40'000 that we need to know for sendig the reply replyMessage.senderSocket(requestMessage.senderSocket()); replyMessage.recipientSocket(requestMessage.recipientSocket()); replyMessage.setRecipient(requestMessage.getSender()); replyMessage.setSender(peerBean().serverPeerAddress()); replyMessage.setCommand(requestMessage.getCommand()); replyMessage.setType(replyType); replyMessage.setVersion(connectionBean().p2pId()); replyMessage.setMessageId(requestMessage.getMessageId()); return replyMessage; } /** * Forwards the request to a handler. * * @param requestMessage * The request message * @return The reply message */ public Message2 forwardMessage(final Message2 requestMessage) { // here we need a referral, since we got contacted and we don't know // if we can contact the peer with its address. The peer may be // behind a NAT peerBean().peerMap().peerFound(requestMessage.getSender(), requestMessage.getSender()); try { Message2 replyMessage = handleResponse(requestMessage, sign); return replyMessage; } catch (Throwable e) { peerBean().peerMap().peerFailed(requestMessage.getSender(), true); if (LOG.isErrorEnabled()) { LOG.error("Exception in custom handler: " + e.toString()); } e.printStackTrace(); return null; } } /** * If the message is OK, that has been previously checked by the user using checkMessage, a reply to the message is * generated here. * * @param message * Request message * @param sign * Flag to indicate if message is signed * @return The message from the handler * @throws Exception * Any exception */ public abstract Message2 handleResponse(Message2 message, boolean sign) throws Exception; }