Re: Vendor packet #23

[email protected] Sat, 6 Mar 2010 17:54:13 +0000 (UTC)
Newsgroups gmane.network.gnutella.devel
Organization Home, Grenoble, France
Message-ID <[email protected]>
Quoting Nikolay Raspopov <[email protected]> from ml.gnutella.dev-forum:
:Hello, [email protected]!
:You wrote to <[email protected]> on Sat, 6 Mar 2010 12:29:00 +0000 (UTC):
:
: RM> :As I know its vendor packet and decoded as Vendor="LIME",
: RM> Function=23, Version=2 :followed by unknown byte "07" and query(?)
: RM> string :"urn:sha1:4HGMT342UDELUECVQZFGGEY2ZNT2XWWJ".
:
: RM> LIME/23v2 is known as "HEAD Ping".
: RM> Its purpose is to request alternate locations for the shared file.
:
:Thanks. And how to reply on this packet?

Well, with a LIME/24v2, known as "HEAD Pong", of course!

The code bits:

enum {
	VMSG_HEAD_CODE_NOT_FOUND	= 0,
	VMSG_HEAD_CODE_COMPLETE		= 1 << 0,
	VMSG_HEAD_CODE_PARTIAL		= 1 << 1,

	VMSG_HEAD_STATUS_FIREWALLED	 = 1 << 2,
	VMSG_HEAD_STATUS_DOWNLOADING = 1 << 3,
	
	VMSG_HEAD_CODE_MASK			= 0x03
};

The payload is made of GGEP keys.

The "C" key has a single byte code, whose bits are defined in the enum
above.

The "Q" key holds a single byte describing the queue status. Don't know
the exact coding of this field.  Probably the number of queue slots available?

The "V" key holds the 4-byte vendor code string, e.g. "GTKG".

The "F" key holds one boolean byte, set to 1 if you support TLS.

The "A" key holds a packed IP:port vector of alt-locs
(port is LE16, IP is BE32).

The "T" key is a bitfield indicating which of the alt locs support TLS.
Format unknown, sorry.  GTKG issues it, but all I have is a C code algorithm
written by Chritian Biere.  Can't tell what the specs are exactly.

Here's the C code:

"hcnt" is the number of alt-locs in the "hvec" array.

    guchar tls_bytes[(G_N_ELEMENTS(hvec) + 7) / 8];
    guint tls_index, tls_length;
    guint i;

    g_assert(hcnt <= G_N_ELEMENTS(hvec));
    memset(tls_bytes, 0, sizeof tls_bytes);
    tls_index = 0;
    tls_length = 0;

    for (i = 0; i < hcnt; i++) {
        host_addr_t addr;
        guint16 port;
        char alt[6];

        if (NET_TYPE_IPV4 != gnet_host_get_net(&hvec[i]))
            continue;

        addr = gnet_host_get_addr(&hvec[i]);
        port = gnet_host_get_port(&hvec[i]);
        poke_be32(&alt[0], host_addr_ipv4(addr));
        poke_le16(&alt[4], port);

        if (tls_cache_lookup(addr, port)) {
            tls_bytes[tls_index >> 3] |= 0x80U >> (tls_index & 7);
            tls_length = (tls_index >> 3) + 1;
        }
        tls_index++;
    }

Then you send in "T" the tls_length first bytes of the tls_bytes[] array.
Hope you can figure it out from this C code.  It's rather clear, but I
would of course have preferred an English comment alongside. :-)

That's all I know, because that is all GTKG currently supports.

All this was done by Christian who reverse-engineered the LimeWire Java code.
I don't read LimeWire's code, so I don't know if there are new features that
LimeWire currently supports that were not implemented by Christian,

Perhaps someone from LimeWire could infirm / confim / complement these notes
so that we have definitive specs.

Raphael