aMule Hacking

May 31, 2007 – 3:19 am

aMule is an open source eMule-like client. It enforces a strict upload/download ratio at the client side: You set the maximum upload rate, and your down rate is limited accordingly. For example, if you allow aMule to use 5 kB/s for upload, your maximum download rate is 20 kB/s. 9 kB/s upload gives you 36 kB/s. 10 kB/s gives you unlimited download bandwidth.

My problem is (or rather, was :) ) this: 36 kB/s for download is very little compared with my ADSL line’s capacity of 180 kB/s. But to get the full speed I need to allow aMule to use 10 kB/s out of about 12 kB/s of upload capacity, which makes web surfing extremely painful (ping google.com gives > 2 secs). I don’t mind sharing my bandwidth, but this is too much.

I tried being a good citizen by doing some traffic shaping with wondershaper at my router, giving aMule traffic low priority compared with web surfing. This isn’t trivial, because aMule uses varying ports at both ends of a connection. I used netstat --program to find the peers and then lowered their priorities by host. This helped matters a bit (reducing latency to about half a second), but surfing still felt sluggish.

So I pulled out the big(ger) guns. I downloaded the aMule source code and found this nice little function in Preferences.cpp:

// Here we slightly limit the users' ability to be a bad citizen: for very low upload rates
// we force a low download rate, so as to discourage this type of leeching.
// We're Open Source, and whoever wants it can do his own mod to get around this, but the
// packaged product will try to enforce good behavior.
//
// Kry note: of course, any leecher mod will be banned asap.
void CPreferences::CheckUlDlRatio()
{
	// Backwards compatibility
	if ( s_maxupload == 0xFFFF )
		s_maxupload = UNLIMITED;

	// Backwards compatibility
	if ( s_maxdownload == 0xFFFF )
		s_maxdownload = UNLIMITED;

	if ( s_maxupload == UNLIMITED )
		return;

	// Enforce the limits
	if ( s_maxupload < 4  ) {
		if ( ( s_maxupload * 3 < s_maxdownload ) || ( s_maxdownload == 0 ) )
			s_maxdownload = s_maxupload * 3 ;
	} else if ( s_maxupload < 10  ) {
		if ( ( s_maxupload * 4 < s_maxdownload ) || ( s_maxdownload == 0 ) )
			s_maxdownload = s_maxupload * 4;
	}
}

So, commented out the ‘Enforce the limits’ section, compiled, and viola — your basic leech mod. Now I was free to set my upload rate to 1 kB/s without affecting my download rate, but I didn’t want to do that because:

  1. I didn’t want to be a leech. As a citizen, I try to follow a set of rules that I believe is scalable. What I mean by ’scalable’ is this: If everyone followed my set of rules, the community would prosper. My rules aren’t necessarily the official ones. For example, I always vote at elections because I believe that if everyone voted it would be good for society. There’s no rule that says you have to vote, but it’s scalable so I do it. Anyway, being a leech on a P2P network is certainly not scalable.
  2. aMule has a ‘credit’ system: When you are on someone’s queue waiting to download a chunk, uploading him some data gives you credit. You use this credit to jump ahead in his queue. The queue wait is typically very long, so jumping ahead is significant. Hence your effective upload rate still affects your download rate, even with the mod.
  3. Leeching clients are banned when they are discovered. As far as I can tell, this is not done automatically, but rather manually by people who notice skewed upload/download ratios.

Fortunately, there is good middle ground: Setting my upload rate to 7 kB/s. At this rate web surfing is smooth, I still share most of my bandwidth, and chances of getting detected are slim to none. Best of all, this is scalable behavior: If everyone set their upload rate to 3 kB/s under their max rate, and got max down rate in return, things would be terrific.

  1. 2 Responses to “aMule Hacking”

  2. Hi.

    1. This code is duplicated, and also resides in PrefsUnifiedDlg.cpp, where I believe it is used for the web interface.

    2. Ever heard of “trickle”?

    By Dan Elharrar on May 31, 2007

  3. > 1. This code is duplicated, and also resides in
    > PrefsUnifiedDlg.cpp, where I believe it is used
    > for the web interface.

    Oh, that is bad form… I figured it was duplicated somewhere because, in the prefs dlg, the field value keeps bouncing back to the limited rate, and has to be set to 0 manually. Thanks!

    Maybe I should refactor this and submit a patch so as to enhance the hacking experience of future leech^H^H^H^H^Hhackers :)

    > 2. Ever heard of “trickle”?

    Nope. Having looked at it, I think my solution is superior, because unintelligently shaping outgoing traffic tends to result in diminishing download rates. At least, that’s my experience with a couple of other shapers, and also seems to occur with trickle and BT.

    That’s hardly surprising: if you start dropping or delaying outgoing ACKs on a download connection, your download rate will suffer. Maybe trickle + amule doesn’t suffer from this, I don’t know.

    By Guy Gur Ari on May 31, 2007

Post a Comment