From Gnutella Developers
Source - [Vendor Messages proposal v 0.1. (http://rfc-gnutella.sourceforge.net/src/vendorMessage.html)]
Vendor-specific messages allow vendors to experiment with new messages without disrupting the regular Gnutella network.
This document defines the framework which is used to define the new vendor-specific messages. Whilst those message are inherently highly specific and free form, they are minimally structured so as to be manageable.
4.2.2 Message format
All vendor-specific message use the new message code 0x31 (49 decimal).
The message code 0x32 (50 decimal) is hereby also reserved for standardized vendor messages, i.e. messages that were initially specified privately as a 0x31 message and which were deemed so generally useful that they were "promoted". There is otherwise no difference between the 0x32 and the 0x31 version of a message, as far as the format goes.
Since all vendor-specific messages are defined within one 0x31 message type, the leading bytes of the payload further define the message as follows:
|0-3||Vendor ID||Case-sensitive sequence of 4 ASCII characters, as with query hits. You can also so view this field as a big-endian unsigned 32-bit integer, so "BEAR" would be 0x42454152.|
|4-5||Sub-selector||Yielding the message type for this vendor ID. This field is a little-endian unsigned 16-bit integer.|
|6-7||Version number||A little-endian unsigned 16-bit integer. Versions traditionally start with 1, but a vendor may choose to start at 0 if he so wishes.|
Note from Raphaël Manfredi regarding the Vendor ID: Yes, it is case-sensitive. All vendors traditionally used upper-cased chars in query hits, and being case-insensitive would not buy us anything but problems.
The type of the vendor-specific message is therefore determined by the tuple (Vendor ID, Sub-selector). For ease of notation, the message from vendor ID "BEAR" bearing sub-selector 34 (for instance) at version 1 will be noted "BEAR/34v1". Hereinafter, when we talk about a "message type", we mean a vendor-specific message type, i.e. a tuple (Vendor ID, Sub-selector). Thus, "BEAR/34" is a message type, and you must understand that it is sent encapsulated within a regular Gnutella message bearing the message code 0x31. The remainder of the payload is defined by the message type. The rules for routing 0x31 messages, value for GUID, ttl, and hops are defined on a message type basis. This specification (version 0.1) only defines messages sent with TTL=1 and hops=0. Unknown messages types, or messages sent with something other than TTL=1 and hops=0 MUST be dropped without prejudice.
During Gnutella handshaking, servents supporting reception of vendor-specific messages compliant with this specification MUST advertise so by emitting the following header:
Note that understanding 0x31 messages simply means that you will read the message and not terminate the connection. It gives no assurance that you will be able to understand and process the received message.
4.2.4 Advertising supported messages
Because the set of vendor-messages supported is not really bounded and can be fairly large, it is not advertised directly in the handshake.
At times, all you want to know is whether a servent supports vendor-messages. This is indicated by the presence of the Vendor-Message field in the handshake. So you blindly send the message, and do not really care whether the other end will act on it or simply ignore it.
On the other hand, some vendor-specific messages may require a reply from the other party. Before sending the message, you need to know whether the other end will support it, so that you do not wait the reply forever, or close the connection if the reply does not come after a timeout, for instance.
Whenever a servent supporting vendor messages meets another servent that has advertised "Vendor-Message" in its handshaking header, it MUST send it a "Messages Supported" message, guaranteed to be understood by all implementations, right after the initial "handshaking ping".
The message is known as "null/0v0". "null" is because the vendor ID field is set with zeros, as in 0x00000000. "0" because the sub-selector ID is 0 in decimal. And "v0" because the only version specified for this message is 0.
The payload of the "null/0v0" message is defined as follows (offset relative to the start of the payload, byte 0 being actually byte 8 in the payload of the encapsulating 0x31 message).
Bytes 0-1: vector size (little-endian unsigned 16-bit integer)
The vector that follows has `vector size' items, of 8 bytes each, all formatted the same way. Each item describes a particular vendor-specific message supported by the servent. The first item of that vector would be:
Bytes 2-5: vendor ID (big-endian, e.g. "GTKG") Bytes 6-7: sub-selector ID (little-endian) Bytes 8-9: version number (little-endian)
If several version numbers are supported for a given sub-selector ID, whether or not all are mentionned depends how backward compatible those messages were. If they are guaranteed to be backward compatible, only the highest version supported (i.e. understood when read) needs to be sent back.
4.2.5 Example - Hops Flow Message
Here is a sample definition for a real vendor-specific message, known as BEAR/4v1, but also as "Hops Flow".
|Payload||unsigned byte: hop value|
This message carries a single 8-bit unsigned integer representing the upper bound value for hops that a servent wishes to see in queries from its neighbors. Only queries whose hops are STRICLY lesser than the threshold are expected to be received. A threshold of 0 therefore requests that NO queries be sent at all, since the minimal valid hop count is 0, for a query originated by an immediate neighbour. A threshold of 1 would limit queries to those originated by immediate neighbours, etc...
This message MUST NOT be routed, and MUST always be sent with TTL=1 and hops=0. The GUID is ignored.
BearShare will use the Hops Flow feature to allow leaves to inform its Ultrapeers that they should turn the forwarding of queries on and off (by setting hops to max_TTL and 0 respectively) based on whether or not the leaf has sharing of files turned on. Setting hops to 0 results in a substantial bandwidth reduction with modem users who have large shared file sets but turn sharing off to speed up downloads.
Gtk-Gnutella also uses the Hops Flow feature between ultrapeers to inform the remote node about a flow-control condition locally and to request that the remote node no longer be sending queries that would immediately be dropped anyway upon reception. In that case, the Hops Flow message is sent ahead of all the other messages in the queue to ensure prompt delivery.
Here is a detailed description of the message payload within the 0x31 Gnutella message:
|0||'B'||ASCII code 0x42|
|1||'E'||ASCII code 0x45|
|2||'A'||ASCII code 0x41|
|3||'R'||ASCII code 0x52|
|4||0x04||lower 8 bits of ID (4)|
|5||0x00||upper 8 bits of ID (4)|
|6||0x01||lower 8 bits of Version (1)|
|7||0x00||upper 8 bits of Version (1)|
|8||zz||the hop value (between 0 and 255)|
Therefore, the payload length for this 0x31 message is 9 bytes.