package com.limegroup.gnutella.messages.vendor;
import java.util.Set;
import org.limewire.collection.IntervalSet;
import org.limewire.io.IpPort;
import com.limegroup.gnutella.PushEndpoint;
import com.limegroup.gnutella.RemoteFileDesc;
import com.limegroup.gnutella.downloader.RemoteFileDescFactory;
/**
* a response to an HeadPing. It is a trimmed down version of the standard HEAD response,
* since we are trying to keep the sizes of the udp packets small.
*
* This message can also be used for punching firewalls if the ping requests so.
* Feature like this can be used to allow firewalled nodes to participate more
* in download meshes.
*
* Since headpings will be sent by clients who have started to download a file whose download
* mesh contains this host, it needs to contain information that will help those clients whether
* this host is a good bet to start an http download from. Therefore, the following information should
* be included in the response:
*
* - available ranges of the file
* - queue status
* - some altlocs (if space permits)
*
* the queue status can be an integer representing how many people are waiting in the queue. If
* nobody is waiting in the queue and we have slots available, the integer can be negative. So if
* we have 3 people on the queue we'd send the integer 3. If we have nobody on the queue and
* two upload slots available we would send -2. A value of 0 means all upload slots are taken but
* the queue is empty. This information can be used by the downloaders to better judge chances of
* successful start of the download.
*
* NEW GGEP FORMAT:
* A GGEP block containing:
* F: features (optional)
* supported features:
* 0x1 = TLS_CAPABLE
* C: response code (required)
* V: vendor id (required if not 404)
* Q: queue status (required if not 404)
* R: ranges (optional, shouldn't be if complete file)
* P: push locations (optional)
* A: direct locations (optional)
* T: indexes of which direct locations support TLS
*
* OLD BINARY FORMAT:
* 1 byte - features byte
* 2 byte - response code
* 4 bytes - vendor id
* 1 byte - queue status
* n*8 bytes - n intervals (if requested && file partial && fits in packet)
* the rest - altlocs (if requested)
*/
public interface HeadPong extends VendorMessage {
public static final int BINARY_VERSION = 1;
public static final int GGEP_VERSION = 2;
public static final int VERSION = 2;
/** GGEP fields in the ggep format of the pong. */
static final String FEATURES = "F";
static final String CODE = "C";
static final String VENDOR = "V";
static final String QUEUE = "Q";
static final String RANGES = "R";
static final String RANGES5 = "R5";
static final String PUSH_LOCS = "P";
static final String LOCS = "A";
static final String TLS_LOCS = "T";
/** Features within the GGEP Features block. */
static final byte TLS_CAPABLE = 0x1;
/**
* instead of using the HTTP codes, use bit values. The first three
* possible values are mutually exclusive though. DOWNLOADING is
* possible only if PARTIAL_FILE is set as well.
*/
static final byte FILE_NOT_FOUND= (byte)0x0;
static final byte COMPLETE_FILE= (byte)0x1;
static final byte PARTIAL_FILE = (byte)0x2;
static final byte FIREWALLED = (byte)0x4;
static final byte DOWNLOADING = (byte)0x8;
static final byte CODES_MASK=(byte)0xF;
/** all our slots are full. */
static final byte BUSY=(byte)0x7F;
/**
*
* @return whether the alternate location still has the file
*/
public boolean hasFile();
/**
*
* @return whether the alternate location has the complete file
*/
public boolean hasCompleteFile();
/**
*
* @return the available ranges the alternate location has
*/
public IntervalSet getRanges();
/**
* @return set of <tt>Endpoint</tt>
* containing any alternate locations this alternate location returned or
* and empty set if not available
*/
public Set<IpPort> getAltLocs();
/**
* @return set of <tt>PushEndpoint</tt>
* containing any firewalled locations this alternate location returned or
* an empty set if not available.
*/
public Set<PushEndpoint> getPushLocs();
/** Whether or not this pong supports TLS. */
public boolean isTLSCapable();
/**
* @return all altlocs carried in the pong as
* set of <tt>RemoteFileDesc</tt>
*/
public Set<RemoteFileDesc> getAllLocsRFD(RemoteFileDesc original, RemoteFileDescFactory remoteFileDescFactory);
/**
*
* @return the remote vendor as string
*/
public String getVendor();
/**
*
* @return whether the remote is firewalled and will need a push
*/
public boolean isFirewalled();
public int getQueueStatus();
public boolean isBusy();
public boolean isDownloading();
/**
* @return true if this pong came from a host that doesn't support routing
*/
public boolean isRoutingBroken();
// TODO: hack to let PingRankerTest compile
public byte[] getPayload();
}