Developers.Gnutella.Notes.LeafModeAndUltrapeerMode
Leaf Mode and Ultrapeer Mode
When a Gnutella program is running on a computer and connecting to other Gnutella programs across the Internet, it can act in one of two roles. If it finds that it has a slow Internet connection, it remains a leaf. If it has a fast connection with an IP address that other computers can connect to, it becomes an ultrapeer.
The leaf and ultrapeer system was invented by LimeWire, and is really complicated. A Gnutella program can be a leaf, an ultrapeer, or not an ultrapeer but capable of becomming one. The role can change as the program runs. I think it's possible for a Gnutella program to be a leaf to some remote computers, and an ultrapeer to others. Additionally, the system was designed to interact with older clients that are just peers - neither leaves or ultrapeers - even though very few are now on the network.
A leaf keeps only a small number of connections open, and that is to ultrapeers. An ultrapeer acts as a proxy to the Gnutella network for the leaves connected to it.
When a leaf connects to an ultrapeer, it is saying, "My Internet connection is so bad I can't really connect to the Gnutella network. So, can I just tell you (the ultrapeer) what I want, and then you can search for me?"
An ultrapeer decides what queries to forward to leaf nodes using the Query Routing Protocol, QRP, see 3.8
OK, so that's what QRP does. A leaf starts out by telling an ultrapeer what it's sharing. The ultrapeer uses this information to not forward a search to a leaf if it knows the leaf doesn't have it. The Query Routing Protocol is how the leaf tells the ultrapeer, all at once, what it has.
The ultrapeer system created some handshake headers. If a computer says:
X-Ultrapeer: True it is an ultrapeer X-Ultrapeer-Needed: True it would like to connect to an ultrapeer X-Query-Routing: 0.1 it supports the query routing protocol for a leaf telling an ultrapeer what it has
Also, just like X-Try lists some IP addresses where we might find Gnutella programs running, X-Try-Ultrapeers lists IP addresses where we might find Gnutella programs running in ultrapeer mode.
Here's an example of what the handshake looks like when a leaf connects to an ultrapeer:
<source lang="c"> leaf ultrapeer
------------
GNUTELLA CONNECT/0.6 User-Agent: LimeWire/1.0 X-Ultrapeer: False X-Query-Routing: 0.1
GNUTELLA/0.6 200 OK User-Agent: LimeWire/1.0 X-Ultrapeer: True X-Ultrapeer-Needed: False X-Query-Routing: 0.1 X-Try: 24.37.144:6346, 193.205.63.22:6346 X-Try-Ultrapeers: 23.35.1.7:6346, 18.207.63.25:6347
GNUTELLA/0.6 200 OK </source>
The leaf says X-Ultrapeer: False, telling the other computer it's a leaf. It says X-Query-Routing: 0.1, meaning it can communicate what it's sharing with QRP.
The ultrapeer says X-Ultrapeer: True, declaring itself as an ultrapeer. It also says X-Query-Routing: 0.1, meaning it can also understand QRP.
The ultrapeer also says X-Ultrapeer-Needed: False. This isn't information the leaf really needs. It just means that the ultrapeer already has enough ultrapeer connections, and doesn't need any more.
The leaf is now a shielded node of the ultrapeer. The leaf should drop any non-ultrapeer connections and send a QRP routing table (assuming QRP is used).
Right. Leaf mode is all about connecting to an ultrapeer, and having that computer work for you. So, once you've adopted leaf mode, you should disconnect from any non-ultrapeer connections. A leaf can't connect to another leaf - that wouldn't be leaf-like. And, you should send your ultrapeer a QRP routing table. It will have a summary of what you are sharing. Your ultrapeer will use it to notice that you're not sharing what someone wants, and then not bother you with that search.
If a shielded leaf node receives a connection request, it will refuse to accept the connection by returning a 503 error code
Two leaves can't be connected. Also, leaves don't accept incoming connections. A leaf just connects to an ultrapeer, and then exists shielded behind it.
When two ultrapeers meet, both set X-Ultrapeer: true. If both have leaf nodes, they will remain ultrapeers after the interaction. Note that no QRP route table is sent between ultrapeers after the connection is established.
So:
- If two ultrapeers connect, and one doesn't have leaves, it becomes a leaf.
- When two ultrapeers connect, they don't exchange QRP tables. They're just between ultrapeers and leaves.
Here's an example of an ultrapeer connecting to another ultrapeer, and becoming a leaf:
<source lang="c"> leafless ultrapeer ultrapeer
------------
GNUTELLA CONNECT/0.6 X-Ultrapeer: True (I am an ultrapeer)
GNUTELLA/0.6 200 OK X-Ultrapeer: True (I am also an ultrapeer, and) X-Ultrapeer-Needed: False (I don't need any more ultrapeer connections)
GNUTELLA/0.6 200 OK X-Ultrapeer: False (OK, I've switched, and I'm a leaf now) </source>
Shareaza devotes a lot of code to ultrapeer and leaf concerns, and LimeWire has done even more work to make them more complicated.