How it works:
The
gnutella protocol makes every
node connected to the network equal. Each node is a server, and each is a client. The term coined for this was "servent", and it prevents the entire network from going down because of a shutdown, or government regulation (in theory. See
JayBonci's writeup for the problem.)
A brodcast
packet on the
network begins from a single node, and is brodcast to each connected
servent. Each of these servents brodcast the same packet to all their connected
servents, and so on. What's to stop a
packet from circulating throughout the network forever you ask? Each packet has a TTL, or "Time To Live" value. The
TTL value gets reduced by 1 when a packet is forwarded.
Some clients will
drop a packet on the floor if the
TTL is too big. In theory, if every servent is connected to 8 other servents, and a packet has a TTL value of 7, it can reach 8
7 servents, which is 2097152 individual nodes.
A
reply packet begins as a response to a brodcast packet. It's forwarded along the same path untill it gets back to the servent that sent the original brodcast packet.
To keep track of where a packet came from, instead of throwing the IP address around, each packet has a 16
byte message ID, which is just
random data. Each servent keeps a hash of the most recent few thousand packets it recieved. The hash table is like a
TCP/IP routing table, it stores the message ID and matches it with the
IP address it came from.
Anonymity is provided because every servent only knows about the servents it's connected to, unless they announce themselves by answering a
ping or replying to a query.
How it works (but more in depth):
Connecting:
The initiator opens a
TCP connection, and sends
"
GNUTELLA CONNECT/0.4\n\n".
Then the receiver sends
"
GNUTELLA OK\n\n"
Then it's all packets
Header:
Bytes 0 to 15: Message ID:
The message ID I described earlier. 16 bytes of random
data
Byte 16: Function
Byte 17: TTL Remaining:
How many hops left before this packet should be dropped
Byte 18: Hops taken:
How many hops this packet has taken
Bytes 19-22: Data Length:
The length of the function-dependant data. A 32 bit unsigned integer.
Little-endian, which is the opposite of
network byte order.
Packet types:
Ping:
A ping has no body, and is routed to every available connection.
Pong:
Bytes 0-1: Servent port:
The port of the listening
servent. 16 bit,
unsigned int in
little-endian
Bytes 2-5: Servent
IP
The
IP address of the listening servent, unsigned
integer in
big-endian
Bytes 6-9: File Count:
The number of files shared by the servent.
32 bit unsigned integer in little-endian
Bytes 10-14: Total Files Size
Total size of the files shared by the servent, in
KB (1024
bytes). 32 bits, unsigned integer in little-endian.
Pong packets are
forwarded through the connection the ping came from
Query:
Bytes 0-1: Minimum
speed:
The minimum speed of servents which should perform the search and send results. 16 bit
unsigned integer in little-endian
Bytes 2+: Search String:
A
NULL zero terminated
character string.
Brodcast to each available connection, except the one it came from.
Hits (Query Response):
Byte 0: Number of Items:
The number Hit Items (see below) which follow this header. An 8 bit unsigned integer (
byte order is irrelevant with one byte).
Bytes 1 - 2: Servent Port:
The listening port number of the servent which found the results. A 16 bit unsigned integer in little-endian byte order.
Bytes 3 - 6: Servent IP:
The
IP address of the servent which found the results. A 32 bit unsigned integer in
network byte order.
Bytes 7 - 8: Servent
Speed:
The speed of the servent which found the results. A 16 bit unsigned integer in
little-endian byte order.
Bytes 9 - 10: Unknown:
Unknown.
Bytes 11 +: List of Items:
A Hits Item (see below) for each result found.
Last 16 Bytes: Response ID:
The Response ID of the servent which found the results. 16 bytes of
random data.
Forward packet only through the connection from which the Query came.
Push Request:
Bytes 0 - 15: Response ID:
The Response ID of the server from which requester wishes to receive a push.
Bytes 16 - 19: File Index:
The File
Index of file requested. See Hit Items for more info. A 32 bit unsigned integer in
little-endian byte order.
Bytes 20 - 23: Requester IP:
The
IP address of the servent requesting the push. A 32 bit unsigned integer in network byte order.
Bytes 24 - 25: Requester
Port:
The Port number of the servent requesting the push. A
16 bit unsigned integer in little-endian byte order.
Forward packet only through the
connection from which the Hits came.
Hits Items:
Bytes 0 - 3: File Index:
Each
file shared by a
servent has an integer value associated with it. A
32 bit unsigned integer in
little-endian byte order.
Bytes 4 - 7: File Size:
The size of the file in
octets. A 32 bit unsigned integer in
little-endian byte order.
Bytes 8 +: Pathname:
The pathname of the found file. The
pathname is double
NULL zero terminated.
Downloading
Downloading is all
HTTP. A GET request is sent, with a uri that is made from the information in the Hit. It starts with /get/, then the File index number, then the filename.
Uploading
Uploading is done in response to a Push Request. The uploader establishes a
TCP connection, and sends GIV, then the File Index number, a colon, the Response ID of the uploader, a slash, the filename, and finally two newlines