com.limegroup.gnutella
Class GUID

java.lang.Object
  extended bycom.limegroup.gnutella.GUID
All Implemented Interfaces:
java.lang.Comparable

public class GUID
extends java.lang.Object
implements java.lang.Comparable

A 16-bit globally unique ID. Immutable.

Let the bytes of a GUID G be labelled G[0]..G[15]. All bytes are unsigned. Let a "short" be a 2 byte little-endian** unsigned number. Let AB be the short formed by concatenating bytes A and B, with B being the most significant byte. LimeWire GUID's have the following properties:

  1. G[8]==0xFF. This serves to identify "new GUIDs", e.g. from BearShare.
  2. G[15]=0x00. This is reserved for future use.
  3. G[9][10]= tag(G[4][5], G[6][7]). This is LimeWire's "secret" proprietary marking.
Here tag(A, B)=OxFFFF & ((A+2)*(B+3) >> 8). In other words, the result is obtained by first taking pair of two byte values and adding "secret" constants. These two byte values are then multiplied together to form a 4 byte product. The middle two bytes of this product are the tag. Sign IS considered during this process, since Java does that by default.

In addition, LimeWire GUIDs may be marked as follows:

  1. G[13][14]=tag(G[0]G[1], G[9][10]). This was used by LimeWire 2.2.0-2.2.3 to mark automatic requeries. Unfortunately these versions inadvertently sent requeries when cancelling uploads or when sometimes encountering a group of busy hosts. VERSION 0
  • G[13][14]=tag(G[0][1], G[2][3]). This marks requeries from versions of LimeWire that have fixed the requery bug, e.g., 2.2.4 and all 2.3s. VERSION 1
  • G[13][14]=tag(G[0][1], G[11][12]). This marks requeries from versions of LimeWire that have much reduced the amount of requeries that can be sent by an individual client. a client can only send 32 requeries amongst ALL requeries a day. VERSION 2 Note that this still leaves 10-12 bytes for randomness. That's plenty of distinct GUID's. And there's only a 1 in 65000 chance of mistakenly identifying a LimeWire. Furthermore, LimeWire GUIDs may be 'marked' by containing address info. In particular:
    1. G[0][3] = 4-octet IP address. G[13][14] = 2-byte port (little endian).
    Note that there is no way to tell from a guid if it has been marked in this manner. You need to have some indication external to the guid (i.e. for queries the minSpeed field might have a bit set to indicate this). Also, this reduces the amount of guids per IP to 2^48 - plenty since IP and port comboes are themselves unique.


    Nested Class Summary
    static class GUID.GUIDByteComparator
              Compares 16-byte arrays (raw GUIDs) lexically.
    static class GUID.GUIDComparator
              Compares GUID's lexically.
     
    Constructor Summary
    GUID()
              Creates a new Globally Unique Identifier (GUID).
    GUID(byte[] bytes)
              Creates a new GUID instance with the specified array of unique bytes.
     
    Method Summary
    static boolean addressesMatch(byte[] guidBytes, byte[] ip, int port)
               
     boolean addressesMatch(byte[] ip, int port)
              Same as addressesMatch(this.bytes, ....)
     byte[] bytes()
              Warning: this exposes the rep! Do not modify returned value.
     int compareTo(java.lang.Object o)
              Compares this GUID to o, lexically.
     boolean equals(java.lang.Object o)
               
    static byte[] fromHexString(java.lang.String sguid)
              Create a GUID bytes from a hex string version.
     java.lang.String getIP()
              Same as getIP(this.bytes)
    static java.lang.String getIP(byte[] guidBytes)
              Gets bytes 0-4 as a dotted ip address.
     int getPort()
              Same as getPort(this.bytes)
    static int getPort(byte[] guidBytes)
              Gets bytes 13-14 as a port.
     int hashCode()
               
     boolean isLimeGUID()
              Same as isLimeGUID(this.bytes)
    static boolean isLimeGUID(byte[] bytes)
              Returns true if this is a specially marked LimeWire GUID.
     boolean isLimeRequeryGUID()
              Same is isLimeRequeryGUID(this.bytes)
    static boolean isLimeRequeryGUID(byte[] bytes)
              Returns true if this is a specially marked Requery GUID from any version of LimeWire.
    static boolean isLimeRequeryGUID(byte[] bytes, int version)
              Returns true if this is a specially marked LimeWire Requery GUID.
     boolean isLimeRequeryGUID(int version)
              Same as isLimeRequeryGUID(this.bytes, version)
     boolean isNewGUID()
              Same as isNewGUID(this.bytes).
    static boolean isNewGUID(byte[] bytes)
              Returns true if this is a GUID from newer Gnutella clients, e.g., LimeWire and BearShare.
     boolean isWindowsGUID()
              Same as isWindowsGUID(this.bytes).
    static boolean isWindowsGUID(byte[] bytes)
              Returns true if this is a GUID created by the Windows CoCreateGUID() routine.
    static byte[] makeAddressEncodedGuid(byte[] ip, int port)
              Create a guid with an ip and port encoded within.
    static byte[] makeGuid()
              Returns the bytes for a new GUID.
    static byte[] makeGuidRequery()
               
     java.lang.String toHexString()
              Create a hex version of a GUID for compact display and storage Note that the client guid should be read in with the Integer.parseByte(String s, int radix) call like this in reverse
     java.lang.String toString()
               
     
    Methods inherited from class java.lang.Object
    clone, finalize, getClass, notify, notifyAll, wait, wait, wait
     

    Constructor Detail

    GUID

    public GUID()
    Creates a new Globally Unique Identifier (GUID).


    GUID

    public GUID(byte[] bytes)
    Creates a new GUID instance with the specified array of unique bytes.

    Parameters:
    bytes - the array of unique bytes
    Method Detail

    makeGuid

    public static byte[] makeGuid()
    Returns the bytes for a new GUID.


    makeGuidRequery

    public static byte[] makeGuidRequery()
    Returns:
    the bytes for a new GUID flagged to be a requery made by LW.

    makeAddressEncodedGuid

    public static byte[] makeAddressEncodedGuid(byte[] ip,
                                                int port)
                                         throws java.lang.IllegalArgumentException
    Create a guid with an ip and port encoded within.

    Throws:
    java.lang.IllegalArgumentException - thrown if ip.length != 4 or if the port is not a valid value.

    isLimeGUID

    public boolean isLimeGUID()
    Same as isLimeGUID(this.bytes)


    isLimeRequeryGUID

    public boolean isLimeRequeryGUID(int version)
    Same as isLimeRequeryGUID(this.bytes, version)


    isLimeRequeryGUID

    public boolean isLimeRequeryGUID()
    Same is isLimeRequeryGUID(this.bytes)


    addressesMatch

    public boolean addressesMatch(byte[] ip,
                                  int port)
                           throws java.lang.IllegalArgumentException
    Same as addressesMatch(this.bytes, ....)

    Throws:
    java.lang.IllegalArgumentException

    getIP

    public java.lang.String getIP()
    Same as getIP(this.bytes)


    getPort

    public int getPort()
    Same as getPort(this.bytes)


    isLimeGUID

    public static boolean isLimeGUID(byte[] bytes)
    Returns true if this is a specially marked LimeWire GUID. This does NOT mean that it's a new GUID as well; the caller will probably want to check that.


    isLimeRequeryGUID

    public static boolean isLimeRequeryGUID(byte[] bytes)
    Returns true if this is a specially marked Requery GUID from any version of LimeWire. This does NOT mean that it's a new GUID as well; the caller will probably want to check that.


    isLimeRequeryGUID

    public static boolean isLimeRequeryGUID(byte[] bytes,
                                            int version)
    Returns true if this is a specially marked LimeWire Requery GUID. This does NOT mean that it's a new GUID as well; the caller will probably want to check that.

    Parameters:
    version - The version of RequeryGUID you want to test for. 0 for requeries up to 2.2.4, 1 for requeries between 2.2.4 and all 2.3s, and 2 for current requeries....

    isWindowsGUID

    public final boolean isWindowsGUID()
    Same as isWindowsGUID(this.bytes).


    isWindowsGUID

    public static boolean isWindowsGUID(byte[] bytes)
    Returns true if this is a GUID created by the Windows CoCreateGUID() routine. Note that the converse does not hold; this method may also return true for other randomly generated GUID's.


    addressesMatch

    public static boolean addressesMatch(byte[] guidBytes,
                                         byte[] ip,
                                         int port)
                                  throws java.lang.IllegalArgumentException
    Returns:
    true if the input ip and port match the one encoded in the guid.
    Throws:
    java.lang.IllegalArgumentException - thrown if ip.length != 4 or if the port is not a valid value.

    getIP

    public static java.lang.String getIP(byte[] guidBytes)
    Gets bytes 0-4 as a dotted ip address.


    getPort

    public static int getPort(byte[] guidBytes)
    Gets bytes 13-14 as a port.


    isNewGUID

    public final boolean isNewGUID()
    Same as isNewGUID(this.bytes).


    isNewGUID

    public static boolean isNewGUID(byte[] bytes)
    Returns true if this is a GUID from newer Gnutella clients, e.g., LimeWire and BearShare.


    compareTo

    public int compareTo(java.lang.Object o)
    Compares this GUID to o, lexically. Throws ClassCastException if o not a GUID.

    Specified by:
    compareTo in interface java.lang.Comparable

    equals

    public boolean equals(java.lang.Object o)

    hashCode

    public int hashCode()

    bytes

    public byte[] bytes()
    Warning: this exposes the rep! Do not modify returned value.


    toString

    public java.lang.String toString()

    toHexString

    public java.lang.String toHexString()
    Create a hex version of a GUID for compact display and storage Note that the client guid should be read in with the Integer.parseByte(String s, int radix) call like this in reverse


    fromHexString

    public static byte[] fromHexString(java.lang.String sguid)
                                throws java.lang.IllegalArgumentException
    Create a GUID bytes from a hex string version. Throws IllegalArgumentException if sguid is not of the proper format.

    Throws:
    java.lang.IllegalArgumentException