For those unfamiliar, Limewire is a very famous P2P file sharing application. It was not the most popular a few years ago, but it is one of the oldest still remaining (Bearshare practically dissapeared, Kazzaa also, and I might forget others). Consumers like it because it is easy to use, and many people use it (with the potential of finding more files). Developers like it because it is open source, and well documented. I like it because it is the only one that has allowed me to do clean and fast small modifications to the code. Limewire uses the open source Gnutella P2P protocol. That is cool also because this protocol is easy, short and public.
The topic here is to hack Limewire for the following purposes:
- Content-Encoding: deflate. Make it use connections with the deflate option. Meaning the communication between peers is not going to be compressed (the default way) but uncompressed. This hack will mean more bytes being sent and received. For me it’s perfect because I need to see what is going on (trace the behavior of the Gnutella protocol).
- Force Ultrapeer mode. Make it connect to the network as an ultrapeer the minute it starts.
What you need first
Of course, I am talking about modifying Limewire. So, you need the code, and a tool to modify it. Check on Limewire’s website, more precisely here, how to do it. I did it the cool way, using Eclipse. You need Java, so install the latest JDK first. I downloaded Eclipse, then downloaded the latest Limewire code through the CVS, played with it, got lost in it, found some clues and then solved the problem. So, hands on!
1. Content-Encoding: deflate
This is the option used by a Gnutella node to advertise that it supports compression. Because compression saves bytes, and thus bandwidth, it is used as default by all peers in Limewire. And there is no manual way to change it. This is simple as modifying the following file:
LimeWire/core/com/limegroup/gnutella/settings/ConnectionSettings.java
and from it, the following field:
public static final BooleanSetting ENCODE_DEFLATE =
FACTORY.createBooleanSetting(“ENCODE_GNUTELLA_DEFLATE“, true);
Change it to this:
public static final BooleanSetting ENCODE_DEFLATE =
FACTORY.createBooleanSetting(“ENCODE_GNUTELLA_DEFLATE“, false);
2. Force Ultrapeer mode
Limewire will connect as a leaf almost always. There is no precise (at least public) way to know when your node will turn into an ultrapeer. The say is that after several hours of being up (some say days), and sharing many files with a large bandwidth, and running on a very good, you have 50% chances to turn into an ultrapeer. Of course, you might also not turn. I needed to run as an ultrapeer for research purposes (I am being clear here, my interest is NOT sharing files, NOT downloading files and NOT helping others do so). So, I got to find the way to make Limewire do so.
To be sure I turned into an ultrapeer immediately, I followed all the possible suggestions. Thanks to this post in Limewire’s forum, I modified the following file:
LimeWire/core/com/limegroup/gnutella/ConnectionManagerImpl.java
and from it, the following methods:
- public boolean isSupernode(): I changed so that it returns TRUE always. This method is referenced in the code when asking if the node is Supernode or not. I have to note that I guess this change is not needed. This is the first change I did, and I just saw the node connecting to 32 ultrapeers. So this helps if more peers are wanted.
- public boolean isShieldedLeaf(): I changed to return FALSE always. This method is referenced in the code to check if the node is a leaf or not. Shielded means that it will not accept a new connection. FALSE means is not a shielded leaf, so it is clear to accept new connections.
- public boolean isSupernodeCapable(): I changed to return TRUE always. This is similar to the first method. Actually I would think the first one is the right one, but didn’t work for me. This should be used to check if the node can actually be a supernode (ultrapeer should be the same in this case). For example, Limewire has an option in the GUI to avoid becoming an ultrapeer. I suppose this method checks that check in the GUI. I didn’t care, so I return a TRUE always.
I tried first modifying the first method, and as I said, the node connected to 32 ultrapeers. But didn’t accept new connections. (the response in the traces used the code 503, replying it was a leaf also as the node it was trying to connect to it). I then tried changing the last two methods (and left the first one returning TRUE) and it worked. Now it says: zero ultrapeers, 32 peers and 32 leafs. Yeaii!