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 87 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