package com.limegroup.gnutella;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import org.limewire.core.settings.ApplicationSettings;
import org.limewire.io.NetworkUtils;
import com.limegroup.gnutella.messages.Message;
import com.limegroup.gnutella.messages.PingReply;
import com.limegroup.gnutella.messages.PushRequest;
import com.limegroup.gnutella.messages.QueryReply;
import com.limegroup.gnutella.messages.vendor.SimppVM;
import com.limegroup.gnutella.messages.vendor.UDPCrawlerPong;
import com.limegroup.gnutella.util.DataUtils;
/**
* This class is an implementation of <tt>ReplyHandler</tt> that is
* specialized for handling UDP messages.
*/
public final class UDPReplyHandler implements ReplyHandler {
/** The InetSocketAddress this is for. */
private final InetSocketAddress addr;
private final UDPService udpService;
/** Creates a new UDPReplyHandler for the given address. */
UDPReplyHandler(InetSocketAddress addr, UDPService udpService) {
this.udpService = udpService;
if(!NetworkUtils.isValidSocketAddress(addr))
throw new IllegalArgumentException("invalid addr: " + addr);
this.addr = addr;
}
UDPReplyHandler(InetAddress addr, int port, UDPService udpService) {
this(new InetSocketAddress(addr, port), udpService);
}
/**
* Sends the <tt>PingReply</tt> via a UDP datagram to the IP and port
* for this handler.<p>
*
* Implements <tt>ReplyHandler</tt>.
*
* @param hit the <tt>PingReply</tt> to send
* @param handler the <tt>ReplyHandler</tt> to use for sending the reply
*/
public void handlePingReply(PingReply pong, ReplyHandler handler) {
udpService.send(pong, addr);
}
/**
* Sends the <tt>QueryReply</tt> via a UDP datagram to the IP and port
* for this handler.<p>
*
* Implements <tt>ReplyHandler</tt>.
*
* @param hit the <tt>QueryReply</tt> to send
* @param handler the <tt>ReplyHandler</tt> to use for sending the reply
*/
public void handleQueryReply(QueryReply hit, ReplyHandler handler) {
udpService.send(hit, addr);
}
/**
* Sends the <tt>QueryRequest</tt> via a UDP datagram to the IP and port
* for this handler.<p>
*
* Implements <tt>ReplyHandler</tt>.
*
* @param request the <tt>QueryRequest</tt> to send
* @param handler the <tt>ReplyHandler</tt> to use for sending the reply
*/
public void handlePushRequest(PushRequest request, ReplyHandler handler) {
udpService.send(request, addr);
}
public void countDroppedMessage() {}
public boolean isOpen() {
return true;
}
public int getNumMessagesReceived() {
return 0;
}
public boolean isOutgoing() {
return false;
}
// inherit doc comment
public boolean isKillable() {
return false;
}
/**
* Implements <tt>ReplyHandler</tt>. This always returns <tt>false</tt>
* for UDP reply handlers, as leaves are always connected via TCP.
*
* @return <tt>false</tt>, as all leaves are connected via TCP, so
* directly connected leaves will not have <tt>UDPReplyHandler</tt>s
*/
public boolean isSupernodeClientConnection() {
return false;
}
/**
* Implements <tt>ReplyHandler</tt> interface. Always returns
* <tt>false</tt> because leaves are connected via TCP, not UDP.
*
* @return <tt>false</tt>, since leaves never maintain their connections
* via UDP, only TCP
*/
public boolean isLeafConnection() {
return false;
}
/**
* Returns whether or not this connection is a high-degree connection,
* meaning that it maintains a high number of intra-Ultrapeer connections.
* In the case of UDP reply handlers, this always returns <tt>false<tt>.
*
* @return <tt>false</tt> because, by definition, a UDP 'connection' is not
* a connection at all
*/
public boolean isHighDegreeConnection() {
return false;
}
/**
* Returns <tt>false</tt> since UDP reply handlers are not TCP
* connections in the first place.
*
* @return <tt>false</tt>, since UDP handlers are not connections in
* the first place, and therefore cannot use Ultrapeer query routing
*/
public boolean isUltrapeerQueryRoutingConnection() {
return false;
}
/**
* Returns <tt>false</tt>, as this node is not a "connection"
* in the first place, and so could never have sent the requisite
* headers.
*
* @return <tt>false</tt>, as this node is not a real connection
*/
public boolean isGoodUltrapeer() {
return false;
}
/**
* Returns <tt>false</tt>, as this node is not a "connection"
* in the first place, and so could never have sent the requisite
* headers.
*
* @return <tt>false</tt>, as this node is not a real connection
*/
public boolean isGoodLeaf() {
return false;
}
/**
* Returns <tt>false</tt>, since we don't know whether a host
* communicating via UDP supports pong caching or not.
*
* @return <tt>false</tt> since we don't know if this node supports
* pong caching or not
*/
public boolean supportsPongCaching() {
return false;
}
/**
* Returns whether or not to allow new pings from this <tt>ReplyHandler</tt>.
* Since this ping is over UDP, we'll always allow it.
*
* @return <tt>true</tt> since this ping is received over UDP
*/
public boolean allowNewPings() {
return true;
}
/**
* As of now there is no need to send SimppMessages via UDP,
*/
public void handleSimppVM(SimppVM simppVM) {
//This should never happen. But if it does, ignore it and move on
return;
}
public InetSocketAddress getInetSocketAddress() {
return addr;
}
// inherit doc comment
public InetAddress getInetAddress() {
return addr.getAddress();
}
/**
* Retrieves the host address.
*/
public String getAddress() {
return addr.getAddress().getHostAddress();
}
/**
* Returns <tt>false</tt> to indicate that <tt>UDPReplyHandler</tt>s
* should never be considered stable, due to data loss over UDP and lack
* of knowledge as to whether the host is still alive.
*
* @return <tt>false</tt> since UDP handler are never stable
*/
public boolean isStable() {
return false;
}
/**
* implementation of interface. this is not used.
*/
public String getLocalePref() {
return ApplicationSettings.DEFAULT_LOCALE.get();
}
/**
* Overrides toString to print out more detailed information about
* this <tt>UDPReplyHandler</tt>
*/
@Override
public String toString() {
return addr.toString();
}
/**
* sends the response through udp back to the requesting party
*/
public void handleUDPCrawlerPong(UDPCrawlerPong m) {
udpService.send(m, addr);
}
public void reply(Message m) {
udpService.send(m, addr);
}
public int getPort() {
return addr.getPort();
}
public byte[] getClientGUID() {
return DataUtils.EMPTY_GUID;
}
}