LimeWire Consolidated API

org.limewire.io
Class GUID

java.lang.Object
  extended by org.limewire.io.GUID
All Implemented Interfaces:
Comparable<GUID>

public class GUID
extends Object
implements Comparable<GUID>

A 16-byte 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[15]=0x00. This is reserved for future use.
  2. 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.

As of 9/2004, LimeWire GUIDs used to be marked as such:

  • G[8]==0xFF. This serves to identify "new GUIDs", e.g. from BearShare. This marking was deprecated. 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.
    static class GUID.TimedGUID
              Simply couples a GUID with a timestamp.
     
    Field Summary
    static Comparator<byte[]> GUID_BYTE_COMPARATOR
               
    static Comparator<GUID> GUID_COMPARATOR
               
     
    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.
    GUID(String hexString)
              Creates a GUID from a hex string.
     
    Method Summary
    static byte[] addressEncodeGuid(byte[] ret, byte[] ip, int port)
              Modifies the input guid by address encoding it with the ip and port.
    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(GUID o)
              Compares this GUID to o, lexically.
     boolean equals(Object o)
               
    static byte[] fromHexString(String sguid)
              Create a GUID bytes from a hex string version.
     String getIP()
              Same as getIP(this.bytes)
    static 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)
    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()
               
     boolean matchesIP(byte[] bytes)
              Same as matchesIP(this.bytes)
    static boolean matchesIP(byte[] ipBytes, byte[] guidBytes)
              Gets bytes 0-4 as a dotted ip address.
    static long readTimeStamp(byte[] guid)
               
    static void timeStampGuid(byte[] guid)
              encodes the current time in seconds in the guid.
     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
    static String toHexString(byte[] guid)
              Returns a hex string of the guid bytes.
     String toString()
               
     
    Methods inherited from class java.lang.Object
    clone, finalize, getClass, notify, notifyAll, wait, wait, wait
     

    Field Detail

    GUID_COMPARATOR

    public static final Comparator<GUID> GUID_COMPARATOR

    GUID_BYTE_COMPARATOR

    public static final Comparator<byte[]> GUID_BYTE_COMPARATOR
    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

    GUID

    public GUID(String hexString)
    Creates a GUID from a hex string.

    Throws:
    IllegalArgumentException - if the string is invalid, see fromHexString(String).
    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.

    timeStampGuid

    public static void timeStampGuid(byte[] guid)
    encodes the current time in seconds in the guid. This takes away 3 bytes of entropy because it overwrites byte 16. If used together with address encoding, we're left with 4 bytes of entropy (~ 4 billion) (4 ip, 2 port, 4 timestamp, 2 lime mark)


    readTimeStamp

    public static long readTimeStamp(byte[] guid)
    Returns:
    the encoded time in the guid

    makeAddressEncodedGuid

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

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

    addressEncodeGuid

    public static byte[] addressEncodeGuid(byte[] ret,
                                           byte[] ip,
                                           int port)
                                    throws IllegalArgumentException
    Modifies the input guid by address encoding it with the ip and port.

    Throws:
    IllegalArgumentException - thrown if ip.length != 4 or if the port is not a valid value or if the size of the input guid is not 16.

    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 IllegalArgumentException
    Same as addressesMatch(this.bytes, ....)

    Throws:
    IllegalArgumentException

    getIP

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


    matchesIP

    public boolean matchesIP(byte[] bytes)
    Same as matchesIP(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....

    addressesMatch

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

    getIP

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


    matchesIP

    public static boolean matchesIP(byte[] ipBytes,
                                    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.


    compareTo

    public int compareTo(GUID o)
    Compares this GUID to o, lexically.

    Specified by:
    compareTo in interface Comparable<GUID>

    equals

    public boolean equals(Object o)
    Overrides:
    equals in class Object

    hashCode

    public int hashCode()
    Overrides:
    hashCode in class Object

    bytes

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


    toString

    public String toString()
    Overrides:
    toString in class Object

    toHexString

    public 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


    toHexString

    public static String toHexString(byte[] guid)
    Returns a hex string of the guid bytes.


    fromHexString

    public static byte[] fromHexString(String sguid)
                                throws IllegalArgumentException
    Create a GUID bytes from a hex string version.

    Throws:
    IllegalArgumentException - if sguid is not of the proper format.

    LimeWire Consolidated API

    Copyright © 2009. All Rights Reserved.