Developers.Code.CNeighboursWithConnect

From Shareaza Wiki
Jump to navigation Jump to search

CNeighboursWithConnect

The CNeighbours inheritance chain looks scary, until you realize that the classes that make it up contain just a screenful or two of code each. They are all short except for one: CNeighboursWithConnect.

IsG1UltrapeerCapable and IsG2HubCapable are very similar. They may have been the same function at one time, and then to add a subtle difference between between Gnutella and Gnutella2, a developer copied the method and named them G1 and G2. These methods determine if the program running on the local computer could become a Gnutella ultrapeer or a Gnutella2 hub. They look at the hardware specifications, the program settings, how long we've been connected, and data transfer statistics. They return 0 if we can't become an ultrapeer or hub, or a number 1 or more if we can. The higher the number, the better ultrapeer or hub we would likely be.

ConnectTo is the method that calls CShakeNeighbour::ConnectTo. It gets called by Maintain. It takes an IP address from the host cache. It makes sure we're not already connected to it, and it's not in the list of corporate and government IP addresses to avoid. It creates a new CEDNeighbour or CShakeNeighbour object, calls ConnectTo on it, and returns the pointer to the new neighbour.

When Shareaza runs, it listens on a socket for incoming connections. When a remote computer somewhere on the Internet contacts us, the code creates a CHandshake object to accept the socket and look at the first 7 bytes of data from the remote computer. If CHandshake::OnRead finds those bytes are the ASCII text GNUTELLA, it calls OnAccept. This method creates a new CShakeNeighbour object, and calls AttachTo to have it take the socket.

PeerPrune goes down the list of neighbours, closing hub connections we don't need.

IsG2Leaf, IsG2Hub, IsG1Leaf, and IsG1Ultrapeer are all very similar. You can call IsG1Leaf to find out if we are acting as a leaf on the Gnutella network right now. It works by searching the list of neighbours for a connection that is up to an ultrapeer. If it finds such a connection, we must be a leaf on our end of it. Note that Shareaza has these functions, and not one member variable that tells if we are a leaf or not. This is because even within one network and all at the same time, Shareaza can be a leaf to some computers and a hub to others. If the neighbours list has a connection down to a leaf and another connection up to an ultrapeer, both IsG1Ultrapeer and IsG1Leaf will return true.

NeedMoreHubs and NeedMoreLeafs are very similar. They both take a network name, like PROTOCOL_G1 for Gnutella, and count how many hub or leaf connections we have on that network. They then compare this number to one from settings, and return true if we need more connections, or false if we have enough already.

IsHubLoaded compares to the number of connections for a given protocol that we have to a number from settings. If we have more than 75% of the settings limit, it reports that yes, we are loaded.

OnRun calls DoRun on each neighbour in the list, and calls the Maintain method.

Maintain gets called repeatedly and periodically as the program runs. It's part of the Shareaza code's pulse. Here's an example call stack leading to Maintain:


CNetwork::OnRun CNeighbours::OnRun CNeighboursWithConnect::OnRun CNeighboursWithConnect::Maintain

Maintain is also one of the methods that is really long because it handles all 3 networks simultaneously. In places, it loops 3 times to complete the same task for each network. In other parts, there are 3 screenfuls of similar code, one for each network, with very slight differences.

Maintain counts how many connections we have for each network and of each role. It then calculates how many connections we should have for each network and each role. Then, it closes connections or tries to make new ones from the host cache to get the numbers right where we want them to be.