The "Node Info" Vendor-specific Messages Version 1 Raphael Manfredi August 4th, 2006 INTRODUCTION An ultra node should be ideally positionned in the network: it must be connected to well-connected ultra peers. In order for an ultra node to assess its connectivity, we are introducing an information exchange between ultra nodes, allowing them to make sure they are connected to "good" peers. Indeed, in a network with high outdegree and low TTL, keeping a connection with a poorly connected ultra node is not good for the "density" of the network and not good for our leaves which have a lower search horizon. Great care must be taken however to not peruse the information that can be gathered through those messages to isolate poorly connected nodes or to create inordinate amounts of connection churns. Every node deserves the right to participate to the Gnutella network and be given a chance to become a well-connected node. The information gathered through UDP can also prove to be valuable for researchers who study peer-to-peer networks and Gnutella in particular, to assess the level of support of particular features, etc... SPECIFICATIONS Those messages are meant to be used on a TCP connection to gather information about connected peers. However, they can also be sent via UDP in order for UDP host caches to know which hosts can accept connections, for instance. * Node Info Request Name: Node Info Request Vendor: GTKG ID: 22 Version: 1 TTL: 1 Payload: (big-endian) uint32: flags The flags are used to customize the reply that we wish to get, since some of the fields are optional: 0x00000001 include GGEP "DU" (daily average uptime) extension 0x00000002 include GGEP "LOC" (locale) extension 0x00000004 include GGEP "GTKG.IPV6" (IPv6 support) extension 0x00000008 include GGEP "UA" giving the complete user-agent string 0x00000010 include bandwidth information 0x00000020 include TX/RX dropped packets information (TCP only!) 0x00000040 include query hit statistics 0x00000080 include CPU usage statistics 0x00000100 include GGEP "GGEP" listing known extensions (see below) 0x00000200 include GGEP "VMSG" listing vendor messages (see below) * Node Info Reply Name: Node Info Reply Vendor: GTKG ID: 23 Version: 1 TTL: 1 Payload: (big-endian representation for multibyte values) char[4]: vendor code, e.g. { 'G', 'T', 'K', 'G' } byte: running mode (0 = auto, 1 = leaf, 2 = ultra) uint32: answer flags uint32: operating flags byte: amount of "optional features" entries (say n=3) uint32: optional features #1 .. uint32: optional features #3 byte: max amount of ultra nodes (in UP mode) byte: max amount of ultra nodes (in leaf mode) byte: current amount of ultra nodes uint16: max amount of leaves uint16: current amount of leaves byte: TTL limit for messages sent byte: hard TTL limit for messages relayed uint32: startup time uint32: last IP address change (v4/v6 most recent change of used proto) if (answer_flags & 0x10) { uint16: bandwidth flags uint32: Gnutella input b/w limit in KiB/sec (0 = none) uint32: Gnutella output b/w limit in KiB/sec (0 = none) uint32: Leaf input b/w limit in KiB/sec (0 = none) uint32: Leaf output b/w limit in KiB/sec (0 = none) } if (answer_flags & 0x20) { /* Meaningful only when message is sent via TCP */ uint32: dropped TX packets on this connection (flow-control) uint32: dropped RX packets on this connection (bad, flow-control) } if (answer_flags & 0x40) { uint16: max amount of results returned per query hit uint32: amount of individual file hits on shared files uint32: amount of query hits messages returned via TCP uint32: amount of query hits messages returned via UDP (claimed) uint64: total size of qhits returned via TCP (with Gnet header) uint64: total size of qhits returned via UDP (with Gnet header) } if (answer_flags & 0x80) { uint64: total user CPU time used, in milliseconds uint64: total system CPU time used, in milliseconds } The GUID of the Node Info Reply request is a copy of the one used in the Node Info Request. This allows the requester to know which of its requests was finally processed (requests can be lost during UDP transport, or get discarded by the flow-control of the Gnutella TCP connection). The operating flags (dynamic settings) are defined as: 0x00000001 is TCP-firewalled 0x00000002 is UDP-firewalled 0x00000004 is an active member of the DHT 0x00000008 is an ancient version 0x00000010 time synchronized via NTP 0x00000020 running headless as a server 0x00000040 is a passive member of the DHT 0x00000080 allows UDP traffic 0x00000100 advertises public hostname (DNS name instead of IP) 0x00000200 requests OOB in its queries 0x00000400 will act as OOB proxy for leaves 0x00000800 will deliver OOB replies 0x00001000 can punch UDP hole 0x00002000 is official build (pre-compiled for bin distribution) Optional features are listed in an array of 32-bit flags. The amount of entries in the array precedes that array. Currently, only 2 entries (#1 and #2) are defined, but in the future, as the feature set grows, we may provide more entries. A servent will naturally skip over the entries it does not understand. NB: A feature supported is not necessarily enabled by the user. For instance, a servent can support OOB query hit delivery, but the feature may have been disabled by the user. Nonetheless, that servent will indicate that the feature is supported. The optional features #1 are defined as: 0x00000001 supports Browse Host 0x00000002 supports Partial File Sharing 0x00000004 supports Chat 0x00000008 supports Firewall-to-Firewall transfers 0x00000010 supports Push Proxy 0x00000020 supports "What's New?" queries 0x00000040 supports TTH and THEX 0x00000080 supports magnet URIs 0x00000100 supports UHC (can act as UHC server) 0x00000200 supports TCP stream compression 0x00000400 supports UDP payload compression 0x00000800 supports dynamic querying 0x00001000 supports active download queuing 0x00002000 supports passive download queuing 0x00004000 supports GWC-based bootstrapping 0x00008000 supports UHC-based bootstrapping 0x00010000 supports generation of XML meta data in query hits 0x00020000 supports TCP-based crawling 0x00040000 supports UDP-based crawling 0x00080000 supports inter-UP QRP tables 0x00100000 supports large leaf QRP tables (up to 2 MiSlots) 0x00200000 supports HTTP/1.1 "chunked" encoding 0x00400000 supports HTTP/1.1 Retry-After 0x00800000 supports modern "query speed" flags 0x01000000 supports TLS connections 0x02000000 supports OOB hit delivery 0x04000000 supports OOB proxying for leaves 0x08000000 supports BYE with meaningful messages 0x10000000 supports swarming (downloads from multiple hosts) 0x20000000 supports GGEP extensions 0x40000000 supports Content-Encoding negotiation for downloads 0x80000000 supports Content-Encoding negotiation for uploads The optional features #2 are defined as: 0x00000001 supports GUESS queries 0x00000002 supports the Gnutella DHT architecture 0x00000004 supports IPv6 0x00000008 supports bandwidth limiting 0x00000010 supports Gnutella traffic flow control 0x00000020 uses Hops-Flow message for active flow-control 0x00000040 supports HTTP "HEAD" requests 0x00000080 supports alive ping/pongs 0x00000100 supports pong caching (no broadcasting of pings) 0x00000200 forwards duplicate messages coming with higher TTL 0x00000400 supports dynamic query hit throttling 0x00000800 supports leaf-guided queries 0x00001000 serves small chunks without queuing The answer flags is simply an echoing of the flags that were present in the Node Info Request. That way, the issuer of the request does not need to remember the GUID of the request to recall which information it asked for. Furthermore, if some information was requested but the node answering does not know how to report that information, the corresponding bit is zero-ed. In other words, the answer flags represents the information being returned in the Node Info Reply. The bandwidth flags are defined as: 0x0001 b/w pools can steal unused b/w from each other 0x0002 makes uses of IPv4 TOS 0x0004 EMA of Gnutella inter-ultrapeer b/w used at 90+% 0x0008 EMA of Gnutella ultra->leaves b/w used at 90+% 0x0010 outgoing b/w probably saturated (many stalls detected) The "Node Info Reply" should be sent like an "alive pong", i.e. with an urgent priority (put ahead of the transmission queue) when replying through TCP. The GGEP "UA" extension holds a single string (without any trailing NUL) containing the User-Agent string as it would be advertised in a HTTP header. For instance "gtk-gnutella/0.96.2u (2006-08-29; r11932; GTK1; Linux i686)". The GGEP "GGEP" extension is used to list all the known GGEP extensions, not including "GGEP" (obviously supported). The format of the payload is the list of ASCII-only extension names, each separated by a NUL byte. The final extension listed must not have any trailing NUL byte. The GGEP "VMSG" extension is used to list all the supported vendor messages, as an array of 8 bytes, in the same format as the "Supported Messages" vendor message, only there is no array length indication at the beginning, since the length is given by the GGEP extension header. So each 8-byte entry lists: the vendor code (4 bytes), the message ID (2 bytes, little-endian), the message version (2 bytes, little-endian).