Developers.Gnutella.Notes.Handshaking

From Shareaza Wiki
Jump to navigation Jump to search

Handshaking

A Gnutella servent connects itself to the network by establishing a connection with another servent currently on the network ... Once ... a TCP/IP connection to the servent is created, a handshaking sequence is initiated.

Imagine there are two computers on the Internet. One is called client and the other server - but they are both running Gnutella software. The server is externally contactable on the Internet, with the IP address and port number 5.5.5.5:6346.

The client found out about this IP address from a GWebCache. Now, it's going to try to connect to it. The client creates a new socket, and instructs it to connect to 5.5.5.5:6346. The connection works, and the TCP/IP socket is open and connected.

Sockets, by their nature, are peer-to-peer. Now that the socket is open, it doesn't matter which computer initiated the connection. Each computer can send data to the other. It's like a two-way street.

The two computers are connected, but they haven't exchanged any bytes yet. Neither really knows what the other wants.

The first bytes they send are ASCII text characters. A string of ASCII text characters ends with the two bytes \r\n. That's a line of text called a header. A header looks like this:

<source lang="c"> Header-Name: value\r\n </source>

In the handshake, a computer sends a bunch of headers, and then ends them with a blank line, like this:

<source lang="c"> Header-Name: value\r\n Another-Header: another value\r\n Third-Header: 3\r\n Last-Header: the line after this will be blank\r\n \r\n </source>

That makes up a group of headers.

So here's what the computers do when they first connect: The computer that initiated the connection, client, sends a group of headers. They explain the client is running Gnutella, and what its abilities are. They look like this:

<source lang="c"> GNUTELLA CONNECT/0.6\r\n User-Agent: BearShare/1.0\r\n Pong-Caching: 0.1\r\n GGEP: 0.5\r\n \r\n </source>

Then, the computer that got conneced to, the server, responds with a second group of headers. Finally, the connecting computer confirms everythign with a third and final block. So, there are always exactly 3 groups of headers. And they look like this:

<source lang="c"> client server


--------

GNUTELLA CONNECT/0.6\r\n User-Agent: BearShare/1.0\r\n Pong-Caching: 0.1\r\n GGEP: 0.5\r\n \r\n

                               GNUTELLA/0.6 200 OK\r\n
                               User-Agent: BearShare/1.0\r\n
                               Pong-Caching: 0.1\r\n
                               GGEP: 0.5\r\n
                               Private-Data: 5ef89a\r\n
                               \r\n

GNUTELLA/0.6 200 OK\r\n Private-Data: a04fce\r\n \r\n </source>

After that, both computers start sending the binary stream. The binary stream is composed of Gnutella packets, and is probably compressed.

The first line of each header block summarizes what is happening. When two computers successfully connect, it is as shown above:

GNUTELLA CONNECT/0.6 GNUTELLA/0.6 200 OK GNUTELLA/0.6 200 OK

If the server sees the client's headers, and doesn't want to connect, it looks like this:

GNUTELLA CONNECT/0.6 GNUTELLA/0.6 503 Busy

Both computers then disconnect.

The document talks about the older Gnutella 0.4 protocol. Shareaza recently dropped support for Gnutella 0.4. The code that made 0.4 work has been commented out an deleted.

Someday, the version number 0.6 will become 0.7, or something higher. To make sure your Gnutella program still works in this future, it should always say 0.6, but not freak out if a remote computer says 0.7.

The text OK and Reason Why after the status numbers can be anything. Gnutella programs should just parse for 200 and a number that isn't 200.