com.limegroup.gnutella
Class MessageRouter

java.lang.Object
  extended bycom.limegroup.gnutella.MessageRouter
Direct Known Subclasses:
StandardMessageRouter

public abstract class MessageRouter
extends java.lang.Object

One of the three classes that make up the core of the backend. This class' job is to direct the routing of messages and to count those message as they pass through. To do so, it aggregates a ConnectionManager that maintains a list of connections.


Field Summary
protected  byte[] _clientGUID
          The GUID we attach to QueryReplies to allow PushRequests in responses.
protected static ConnectionManager _manager
          Handle to the ConnectionManager to access our TCP connections.
protected  QueryUnicaster UNICASTER
          Constant handle to the QueryUnicaster since it is called upon very frequently.
 
Constructor Summary
protected MessageRouter()
          Creates a MessageRouter.
 
Method Summary
 void broadcastPingRequest(PingRequest ping)
          Broadcasts the ping request to all initialized connections, setting up the proper reply routing.
protected  boolean bufferResponsesForLaterDelivery(QueryRequest query, Response[] resps)
          Stores (for a limited time) the resps for later out-of-band delivery - interacts with handleLimeACKMessage
protected abstract  java.util.List createQueryReply(byte[] guid, byte ttl, long speed, Response[] res, byte[] clientGUID, boolean busy, boolean uploaded, boolean measuredSpeed, boolean isFromMcast)
          Abstract method for creating query hits.
 void forwardQueryRequestToLeaves(QueryRequest query, ReplyHandler handler)
          Forwards the query request to any leaf connections.
 java.lang.String getPingRouteTableDump()
           
 java.lang.String getPushRouteTableDump()
           
 QueryRouteTable getQueryRouteTable()
          Accessor for the most recently calculated QueryRouteTable for this node.
 java.lang.String getQueryRouteTableDump()
           
protected  void handleLimeACKMessage(LimeACKVendorMessage ack, java.net.DatagramPacket datagram)
          Handles a ACK message - looks up the QueryReply and sends it out of band.
 void handleMessage(Message msg, ManagedConnection receivingConnection)
          The handler for all message types.
 void handleMulticastMessage(Message msg, java.net.DatagramPacket datagram)
          The handler for Multicast messages.
protected  void handlePingReply(PingReply reply, ReplyHandler handler)
          The default handler for PingRequests received in ManagedConnection.loopForMessages().
protected  void handlePushProxyRequest(PushProxyRequest ppReq, ManagedConnection source)
          1) confirm that the connection is Ultrapeer to Leaf, then send your listening port in a PushProxyAcknowledgement.
protected  void handlePushRequest(PushRequest request, ReplyHandler handler)
          The default handler for PushRequests received in ManagedConnection.loopForMessages().
 void handleQueryReply(QueryReply queryReply, ReplyHandler handler)
          The default handler for QueryReplies received in ManagedConnection.loopForMessages().
protected  void handleQueryRequest(QueryRequest request, ReplyHandler handler, ResultCounter counter, boolean locallyEvaluate)
          The default handler for QueryRequests received in ManagedConnection.loopForMessages().
protected  void handleQueryStatus(QueryStatusResponse resp, ManagedConnection leaf)
          This method should be invoked when this node receives a QueryStatusResponse message from the wire.
protected  void handleTCPConnectBackRequest(TCPConnectBackVendorMessage tcp, Connection source)
          Basically, just get the correct parameters, create a Socket, and send a "/n/n".
protected  void handleUDPConnectBackRequest(UDPConnectBackVendorMessage udp, Connection source)
          Basically, just get the correct parameters, create a temporary DatagramSocket, and send a Ping.
 void handleUDPMessage(Message msg, java.net.DatagramPacket datagram)
          The handler for all message types.
protected  void handleUDPPingReply(PingReply reply, ReplyHandler handler, java.net.InetAddress address, int port)
           
protected  void handleUDPPingRequest(PingRequest pingRequest, ReplyHandler handler, java.net.DatagramPacket datagram)
          The default handler for PingRequests received in ManagedConnection.loopForMessages().
protected  boolean hasValidQueryKey(java.net.InetAddress ip, int port, QueryRequest qr)
          Returns true if the Query has a valid QueryKey.
 void initialize()
          Links the MessageRouter up with the other back end pieces
protected  void multicastQueryRequest(QueryRequest query)
          Send the query to the multicast group.
 void originateQuery(QueryRequest query, ManagedConnection mc)
          Originates a new query request to the ManagedConnection.
 void removeConnection(ReplyHandler rh)
          A callback for ConnectionManager to clear a ReplyHandler from the routing tables when the connection is closed.
protected abstract  void respondToPingRequest(PingRequest request, ReplyHandler handler)
          Respond to the ping request.
protected abstract  boolean respondToQueryRequest(QueryRequest queryRequest, byte[] clientGUID)
          Respond to the query request.
protected abstract  void respondToUDPPingRequest(PingRequest request, java.net.DatagramPacket datagram, ReplyHandler handler)
          Responds to a ping received over UDP -- implementations handle this differently from pings received over TCP, as it is assumed that the requester only wants pongs from other nodes that also support UDP messaging.
 java.util.Iterator responsesToQueryReplies(Response[] responses, QueryRequest queryRequest)
          Converts the passed responses to QueryReplies.
protected  void sendAcknowledgement(java.net.DatagramPacket datagram, byte[] guid)
          Sends an ack back to the GUESS client node.
 void sendDynamicQuery(QueryRequest query)
          Generates a new dynamic query.
protected  void sendMulticastPushRequest(PushRequest push)
          Sends a push request to the multicast network.
protected  void sendPingReply(PingReply pong, ReplyHandler handler)
          Uses the ping route table to send a PingReply to the appropriate connection.
 void sendPingRequest(PingRequest request, ManagedConnection connection)
          Sends the ping request to the designated connection, setting up the proper reply routing.
 void sendPushRequest(PushRequest push)
          Uses the push route table to send a push request to the appropriate connection.
protected  void sendQueryKeyPong(PingRequest pr, java.net.DatagramPacket datagram)
          Generates a QueryKey for the source (described by datagram) and sends the QueryKey to it via a QueryKey pong....
protected  void sendQueryReply(QueryReply queryReply)
          Uses the query route table to send a QueryReply to the appropriate connection.
 void sendQueryRequest(QueryRequest request, ManagedConnection connection)
          Sends the query request to the designated connection, setting up the proper reply routing.
 void sendQueryRequest(QueryRequest request, ManagedConnection sendConnection, ReplyHandler handler)
          Sends the passed query request, received on handler, to the passed sendConnection, only if the handler and the sendConnection are authenticated to a common domain To only send it the route table has a hit, use sendRoutedQueryToHost.
protected  void unicastQueryRequest(QueryRequest query, ReplyHandler conn)
          Adds the QueryRequest to the unicaster module.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

_manager

protected static ConnectionManager _manager
Handle to the ConnectionManager to access our TCP connections.


_clientGUID

protected byte[] _clientGUID
The GUID we attach to QueryReplies to allow PushRequests in responses.


UNICASTER

protected final QueryUnicaster UNICASTER
Constant handle to the QueryUnicaster since it is called upon very frequently.

Constructor Detail

MessageRouter

protected MessageRouter()
Creates a MessageRouter. Must call initialize before using.

Method Detail

initialize

public void initialize()
Links the MessageRouter up with the other back end pieces


getPingRouteTableDump

public java.lang.String getPingRouteTableDump()

getQueryRouteTableDump

public java.lang.String getQueryRouteTableDump()

getPushRouteTableDump

public java.lang.String getPushRouteTableDump()

removeConnection

public void removeConnection(ReplyHandler rh)
A callback for ConnectionManager to clear a ReplyHandler from the routing tables when the connection is closed.


handleMessage

public void handleMessage(Message msg,
                          ManagedConnection receivingConnection)
The handler for all message types. Processes a message based on the message type.

Parameters:
receivingConnection - the ManagedConnection over which the message was received

handleUDPMessage

public void handleUDPMessage(Message msg,
                             java.net.DatagramPacket datagram)
The handler for all message types. Processes a message based on the message type.

Parameters:
msg - the Message received
datagram - the DatagramPacket containing the IP and port of the client node

handleMulticastMessage

public void handleMulticastMessage(Message msg,
                                   java.net.DatagramPacket datagram)
The handler for Multicast messages. Processes a message based on the message type.

Parameters:
msg - the Message recieved.
datagram - the DatagramPacket containing the IP and port of the client node.

hasValidQueryKey

protected boolean hasValidQueryKey(java.net.InetAddress ip,
                                   int port,
                                   QueryRequest qr)
Returns true if the Query has a valid QueryKey. false if it isn't present or valid.


sendAcknowledgement

protected void sendAcknowledgement(java.net.DatagramPacket datagram,
                                   byte[] guid)
Sends an ack back to the GUESS client node.


handleUDPPingRequest

protected void handleUDPPingRequest(PingRequest pingRequest,
                                    ReplyHandler handler,
                                    java.net.DatagramPacket datagram)
The default handler for PingRequests received in ManagedConnection.loopForMessages(). This implementation updates stats, does the broadcast, and generates a response. You can customize behavior in three ways: 1. Override. You can assume that duplicate messages (messages with the same GUID that arrived via different paths) have already been filtered. If you want stats updated, you'll have to call super.handlePingRequest. 2. Override broadcastPingRequest. This allows you to use the default handling framework and just customize request routing. 3. Implement respondToPingRequest. This allows you to use the default handling framework and just customize responses.


sendQueryKeyPong

protected void sendQueryKeyPong(PingRequest pr,
                                java.net.DatagramPacket datagram)
Generates a QueryKey for the source (described by datagram) and sends the QueryKey to it via a QueryKey pong....


handleUDPPingReply

protected void handleUDPPingReply(PingReply reply,
                                  ReplyHandler handler,
                                  java.net.InetAddress address,
                                  int port)

handleQueryRequest

protected void handleQueryRequest(QueryRequest request,
                                  ReplyHandler handler,
                                  ResultCounter counter,
                                  boolean locallyEvaluate)
The default handler for QueryRequests received in ManagedConnection.loopForMessages(). This implementation updates stats, does the broadcast, and generates a response. You can customize behavior in three ways: 1. Override. You can assume that duplicate messages (messages with the same GUID that arrived via different paths) have already been filtered. If you want stats updated, you'll have to call super.handleQueryRequest. 2. Override broadcastQueryRequest. This allows you to use the default handling framework and just customize request routing. 3. Implement respondToQueryRequest. This allows you to use the default handling framework and just customize responses.

Parameters:
locallyEvaluate - false if you don't want to send the query to leaves and yourself, true otherwise....

handleLimeACKMessage

protected void handleLimeACKMessage(LimeACKVendorMessage ack,
                                    java.net.DatagramPacket datagram)
Handles a ACK message - looks up the QueryReply and sends it out of band.


bufferResponsesForLaterDelivery

protected boolean bufferResponsesForLaterDelivery(QueryRequest query,
                                                  Response[] resps)
Stores (for a limited time) the resps for later out-of-band delivery - interacts with handleLimeACKMessage

Returns:
true if the operation failed, false if not (i.e. too busy)

handleUDPConnectBackRequest

protected void handleUDPConnectBackRequest(UDPConnectBackVendorMessage udp,
                                           Connection source)
Basically, just get the correct parameters, create a temporary DatagramSocket, and send a Ping.


handleTCPConnectBackRequest

protected void handleTCPConnectBackRequest(TCPConnectBackVendorMessage tcp,
                                           Connection source)
Basically, just get the correct parameters, create a Socket, and send a "/n/n".


handlePushProxyRequest

protected void handlePushProxyRequest(PushProxyRequest ppReq,
                                      ManagedConnection source)
1) confirm that the connection is Ultrapeer to Leaf, then send your listening port in a PushProxyAcknowledgement. 2) Also cache the client's client GUID.


handleQueryStatus

protected void handleQueryStatus(QueryStatusResponse resp,
                                 ManagedConnection leaf)
This method should be invoked when this node receives a QueryStatusResponse message from the wire. If this node is an Ultrapeer, we should update the Dynamic Querier about the status of the leaf's query.


sendPingRequest

public void sendPingRequest(PingRequest request,
                            ManagedConnection connection)
Sends the ping request to the designated connection, setting up the proper reply routing.


sendQueryRequest

public void sendQueryRequest(QueryRequest request,
                             ManagedConnection connection)
Sends the query request to the designated connection, setting up the proper reply routing.


broadcastPingRequest

public void broadcastPingRequest(PingRequest ping)
Broadcasts the ping request to all initialized connections, setting up the proper reply routing.


sendDynamicQuery

public void sendDynamicQuery(QueryRequest query)
Generates a new dynamic query. This method is used to send a new dynamic query from this host (the user initiated this query directly, so it's replies are intended for this node.

Parameters:
query - the QueryRequest instance that generates queries for this dynamic query
Throws:
NullPointerException - if the QueryHandler argument is null

forwardQueryRequestToLeaves

public final void forwardQueryRequestToLeaves(QueryRequest query,
                                              ReplyHandler handler)
Forwards the query request to any leaf connections.

Parameters:
handler - the ReplyHandler that responds to the request appropriately

unicastQueryRequest

protected void unicastQueryRequest(QueryRequest query,
                                   ReplyHandler conn)
Adds the QueryRequest to the unicaster module. Not much work done here, see QueryUnicaster for more details.


multicastQueryRequest

protected void multicastQueryRequest(QueryRequest query)
Send the query to the multicast group.


sendQueryRequest

public void sendQueryRequest(QueryRequest request,
                             ManagedConnection sendConnection,
                             ReplyHandler handler)
Sends the passed query request, received on handler, to the passed sendConnection, only if the handler and the sendConnection are authenticated to a common domain To only send it the route table has a hit, use sendRoutedQueryToHost.

Parameters:
sendConnection - The connection on which to send out the query
handler - The connection on which we originally received the query

originateQuery

public void originateQuery(QueryRequest query,
                           ManagedConnection mc)
Originates a new query request to the ManagedConnection.

Parameters:
mc - The ManagedConnection to send the query along

respondToPingRequest

protected abstract void respondToPingRequest(PingRequest request,
                                             ReplyHandler handler)
Respond to the ping request. Implementations typically will either do nothing (if they don't think a response is appropriate) or call sendPingReply(PingReply). This method is called from the default handlePingRequest.


respondToUDPPingRequest

protected abstract void respondToUDPPingRequest(PingRequest request,
                                                java.net.DatagramPacket datagram,
                                                ReplyHandler handler)
Responds to a ping received over UDP -- implementations handle this differently from pings received over TCP, as it is assumed that the requester only wants pongs from other nodes that also support UDP messaging.

Parameters:
request - the PingRequest to service
datagram - the DatagramPacket containing the ping
handler - the ReplyHandler instance from which the ping was received and to which pongs should be sent

respondToQueryRequest

protected abstract boolean respondToQueryRequest(QueryRequest queryRequest,
                                                 byte[] clientGUID)
Respond to the query request. Implementations typically will either do nothing (if they don't think a response is appropriate) or call sendQueryReply(QueryReply). This method is called from the default handleQueryRequest.


handlePingReply

protected void handlePingReply(PingReply reply,
                               ReplyHandler handler)
The default handler for PingRequests received in ManagedConnection.loopForMessages(). This implementation uses the ping route table to route a ping reply. If an appropriate route doesn't exist, records the error statistics. On sucessful routing, the PingReply count is incremented.

In all cases, the ping reply is recorded into the host catcher.

Override as desired, but you probably want to call super.handlePingReply if you do.


handleQueryReply

public void handleQueryReply(QueryReply queryReply,
                             ReplyHandler handler)
The default handler for QueryReplies received in ManagedConnection.loopForMessages(). This implementation uses the query route table to route a query reply. If an appropriate route doesn't exist, records the error statistics. On sucessful routing, the QueryReply count is incremented.

Override as desired, but you probably want to call super.handleQueryReply if you do. This is public for testing purposes.


handlePushRequest

protected void handlePushRequest(PushRequest request,
                                 ReplyHandler handler)
The default handler for PushRequests received in ManagedConnection.loopForMessages(). This implementation uses the push route table to route a push request. If an appropriate route doesn't exist, records the error statistics. On sucessful routing, the PushRequest count is incremented. Override as desired, but you probably want to call super.handlePushRequest if you do.


sendPingReply

protected void sendPingReply(PingReply pong,
                             ReplyHandler handler)
Uses the ping route table to send a PingReply to the appropriate connection. Since this is used for PingReplies orginating here, no stats are updated.


sendQueryReply

protected void sendQueryReply(QueryReply queryReply)
                       throws java.io.IOException
Uses the query route table to send a QueryReply to the appropriate connection. Since this is used for QueryReplies orginating here, no stats are updated.

Throws:
java.io.IOException - if no appropriate route exists.

sendPushRequest

public void sendPushRequest(PushRequest push)
                     throws java.io.IOException
Uses the push route table to send a push request to the appropriate connection. Since this is used for PushRequests orginating here, no stats are updated.

Throws:
java.io.IOException - if no appropriate route exists.

sendMulticastPushRequest

protected void sendMulticastPushRequest(PushRequest push)
Sends a push request to the multicast network. No lookups are performed in the push route table, because the message will always be broadcast to everyone.


responsesToQueryReplies

public java.util.Iterator responsesToQueryReplies(Response[] responses,
                                                  QueryRequest queryRequest)
Converts the passed responses to QueryReplies. Each QueryReply can accomodate atmost 255 responses. Not all the responses may get included in QueryReplies in case the query request came from a far away host.

NOTE: This method doesnt have any side effect, and does not modify the state of this object

Parameters:
responses - The responses to be converted
queryRequest - The query request corresponding to which we are generating query replies.
Returns:
Iterator (on QueryReply) over the Query Replies

createQueryReply

protected abstract java.util.List createQueryReply(byte[] guid,
                                                   byte ttl,
                                                   long speed,
                                                   Response[] res,
                                                   byte[] clientGUID,
                                                   boolean busy,
                                                   boolean uploaded,
                                                   boolean measuredSpeed,
                                                   boolean isFromMcast)
Abstract method for creating query hits. Subclasses must specify how this list is created.

Returns:
a List of QueryReply instances

getQueryRouteTable

public QueryRouteTable getQueryRouteTable()
Accessor for the most recently calculated QueryRouteTable for this node. If this node is an Ultrapeer, the table will include all data for leaf nodes in addition to data for this node's files.

Returns:
the QueryRouteTable for this node