http://rfc-gnutella.sourceforge.net/developer/testing/transfer.html
It is not always possible to establish a direct connection to a Gnutella servent in an attempt to initiate a file download. The servent may, for example, be behind a firewall that does not permit incoming connections to its Gnutella port. If a direct connection cannot be established, the servent attempting the file download may request that the servent sharing the file "push" the file instead. A servent can request a file push by routing a Push request back to the servent that sent the QueryHit message describing the target file. The servent that is the target of the Push request (identified by the Servent Identifier field of the Push message) SHOULD, upon receipt of the Push message, attempt to establish a new TCP/IP connection to the requesting servent (identified by the IP Address and Port fields of the Push message). If this direct connection cannot be established, then it is likely that the servent that issued the Push request is itself behind a firewall. In this case, file transfer cannot take place by the means of what is described in this document.
Here is the same story, laying out the two computers first and then all the steps in order.
There are two computers: F and E
- F is firewalled. F can connect to other computers, but no computers can connect to F.
- E is externally contactable. E can connect to other computers and other computers can connect to it.
So, F can connect to E, but E can't connect to F.
Both computers are on the Gnutella network. They're not connected directly, but can relay short messages to each other through the Gnutella network.
E is searching for files, and F has a lot of them. Here's what happens:
- E sends a query packet to F
- F has the file E wants, and sends back a query hit packet
Now, all E has to do is connect to F directly, and download the file. E would do this by opening a new socket connection to F, and telling it GET. But, F is firewalled. No one can connect to it. Gnutella has a solution to this problem:
- E sends F a push packet through the Gnutella network that says how to contact E and what file E wants
- F opens a new socket connection to E, telling it GIV, and then starts to send the file
More from RFC
2.8.2.1 Usage of Push Messages
A servent may send a Push message if it receives a QueryHit message from a servent that doesn't support incoming connections. This might occur when the servent sending the QueryHit message is behind a firewall (see the QueryHit EQHD in 2.4 Standard Message Arhitecture). When a servent receives a Push message, it SHOULD act upon the push request if and only if the servent_Identifier field contains the value of its servent identifier. The Message_Id field in the Message Header of the Push message SHOULD not contain the same value as that of the associated QueryHit message, but SHOULD contain a new value generated by the servent's Message_Id generation algorithm.
Push messages are forwarded back to the originator of the Query Hits message using the Servent Identifier value. This means multiple Push messages can have the same Servent Identifier. Push messages MUST only be considered as duplicates if the Message ID in the header is the same. Since Push messages are not broadcasted, duplicate messages should be very rare.
2.8.2.2 - Pushing the file to the downloader
If a direct connection can be established from the firewalled servent to the servent that initiated the Push request, the firewalled servent should immediately send the following:
GIV <File Index>:<Servent Identifier>/<File Name><lf><lf>
Where <File Index> and <Servent Identifier> are the values of the File Index and Servent Identifier fields respectively from the Push request received, and <File Name> is the name of the file in the local file table whose file index number is <File Index>. The File Name MAY be url/uri encoded. The servent that receives the GIV (the servent that wants to receive a file) SHOULD ignore the File Index and File Name, and request the file it wants to download. The servent that sent the GIV MUST allow the client to request any file, and not just the one specified in the Push message. The GET request and the remainder of the file download process is identical to that described in the section 4.1 (Normal File Transfer) above.
The <Servent Identifier> is formatted as hexadecimal, and must be read case-insensitively. For instance:
GIV 36:809BC12168A1852CFF5D7A785833F600/Foo.txt<lf><lf> GIV 124:d51dff817f895598ff0065537c09d503/Bar.html<lf><lf>
If the TCP connection is lost during a Push initiated file transfer, it is strongly RECOMMENDED that the servent who initiated the TCP connection (the servent providing the file) attempt to re-connect. That is important, since the servent receiving the file might not be able to get another Push message to the servent providing the file.

