package com.limegroup.gnutella.messages.vendor;
import java.nio.ByteOrder;
import org.limewire.io.BadGGEPPropertyException;
import org.limewire.io.GGEP;
import org.limewire.io.GUID;
import org.limewire.io.IpPort;
import org.limewire.io.NetworkUtils;
import org.limewire.util.StringUtils;
import com.limegroup.gnutella.messages.BadPacketException;
import com.limegroup.gnutella.messages.Message;
/**
* Message requesting inspection for specified values.
* <p>
* Note this is very LimeWire-specific, so other vendors will
* almost certainly have no use for supporting this message.
*/
public class InspectionRequestImpl extends RoutableGGEPMessage implements InspectionRequest {
static final String INSPECTION_KEY = "I";
static final String TIMESTAMP_KEY = "T";
static final String ENCODING_KEY = "E";
/** Send back encoded responses this often */
private final static int DEFAULT_INTERVAL = 500;
private final String[] requested;
private final boolean timestamp, encoding;
private final int sendInterval;
public InspectionRequestImpl(byte[] guid, byte ttl, byte hops,
int version, byte[] payload, Network network)
throws BadPacketException {
super(guid, ttl, hops, F_LIME_VENDOR_ID, F_INSPECTION_REQ, version, payload, network);
String requested;
try {
requested = ggep.getString(INSPECTION_KEY);
timestamp = ggep.hasKey(TIMESTAMP_KEY);
encoding = ggep.hasKey(ENCODING_KEY);
int interval = DEFAULT_INTERVAL;
try {
interval = ggep.getInt(ENCODING_KEY);
} catch (BadGGEPPropertyException noTime) {}
sendInterval = interval;
} catch (BadGGEPPropertyException bad) {
throw new BadPacketException();
}
this.requested = requested.split(";");
}
InspectionRequestImpl(GGEPSigner signer, String... requested) {
this(new GUID(),signer, false, false, DEFAULT_INTERVAL, 1, null, null, requested);
}
/**
* See <tt>InspectionUtils</tt> for description of the format.
* @param timestamp true if the response should contain a timestamp
* @param requested requested fields for inspection
*/
public InspectionRequestImpl(GUID g, GGEPSigner signer, boolean timestamp,
boolean encoding, int sendInterval, long version, IpPort returnAddr, IpPort destAddress, String... requested) {
super(F_LIME_VENDOR_ID, F_INSPECTION_REQ, VERSION, signer,
deriveGGEP(timestamp, encoding, sendInterval, version, returnAddr, destAddress, requested));
setGUID(g);
this.requested = requested;
this.timestamp = timestamp;
this.encoding = encoding;
this.sendInterval = sendInterval;
}
/* (non-Javadoc)
* @see com.limegroup.gnutella.messages.vendor.InspectionRequest#getRequestedFields()
*/
public String[] getRequestedFields() {
return requested;
}
/* (non-Javadoc)
* @see com.limegroup.gnutella.messages.vendor.InspectionRequest#requestsTimeStamp()
*/
public boolean requestsTimeStamp() {
return timestamp;
}
public boolean supportsEncoding() {
return encoding;
}
/* (non-Javadoc)
* @see com.limegroup.gnutella.messages.vendor.InspectionRequest#setGUID(com.limegroup.gnutella.GUID)
*/
@Override
public void setGUID(GUID g) {
super.setGUID(g);
}
private static GGEP deriveGGEP(boolean timestamp, boolean encoding, int sendInterval, long version, IpPort returnAddr, IpPort destAddr, String... requested) {
/*
* The selected fields are catenated and put in a compressed
* ggep entry.
*/
StringBuilder b = new StringBuilder();
for (String r : requested)
b.append(r).append(";");
String ret;
if (b.charAt(b.length() - 1) == ';')
ret = b.substring(0, b.length() - 1);
else
ret = b.toString();
GGEP g = new GGEP();
g.putCompressed(INSPECTION_KEY, StringUtils.toUTF8Bytes(ret));
if (timestamp)
g.put(TIMESTAMP_KEY);
if (encoding)
g.put(ENCODING_KEY, sendInterval);
if (returnAddr != null) {
g.put(RETURN_ADDRESS_KEY, NetworkUtils.getBytes(returnAddr.getInetAddress(), returnAddr
.getPort(), ByteOrder.LITTLE_ENDIAN));
}
if (destAddr != null) {
g.put(TO_ADDRESS_KEY, NetworkUtils.getBytes(destAddr.getInetAddress(), destAddr
.getPort(), ByteOrder.LITTLE_ENDIAN));
}
if (version >= 0)
g.put(VERSION_KEY, version);
return g;
}
@Override
public Class<? extends Message> getHandlerClass() {
return InspectionRequest.class;
}
public int getSendInterval() {
return sendInterval;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("Requests:\n");
for (String request : requested) {
builder.append(request).append("\n");
}
return builder.toString();
}
}