I work on a Torrent client for AROS in Freepascal, as long as I didn’t find suitable sources for the BitTorrent Protocol, I used mainly the specification. This two pages were very helpful:
Wiki Theory, BitTorrent RFC. But even more useful was to listen to the connections of other Torrent clients with Wireshark. Wireshark knows and decodes the Bittorrent packages and also shows if my program produces an illegal package (wrong size for example).
The first stage was more or less just a dirty first try… very simple, just coded for my two torrent files, and my seeder and tracker on the server (transmission). At 10.08.2014 this was ready to run.. and it downloaded very nicely the little picture… in fact I was really curious if there really arrive a picture or just junk. But (already at first try) the picture looks very good and also a binary diff showed no differences.
If this proof was done I begun completely from zero, made a little sketch for the classes I would need to read/andalyze the torrent file, tracker communication, torrent communication.
I use Lazarus at Linux to write the code. The GUI is LCL for now, but later I think I will change to FPGUI native it just work much better on AROS. I could design own components, for the pieces view for example. Its just much easier to write the code in Lazarus with Code completion and hotkeys for find declaration and online debugging of course. So I try to keep the source compatible between AROS and Linux. And beside one part this worked very nicely.
The parts where I got problems, was the networking… of course… especially the non blocking calls via MSG_DONTWAIT seems not to work at AROS. (Now I know they can not work.. this constant is not present in the whole AROS TCPStack source code, only in the SDK includes ;)). I decided to check for other ways to non blocking calls.. of course one can set the complete socket to nonblocking, but all ways I found in Internet seems not to work on the AROS platform. By looking through the source for „recvfrom“ I found the hint to look for FIONBIO to set with the Ioctl() call (At AROS IoctlSocket()). I don’t know why I didn’t saw it before… Now when I search for nonblocking I can find this solution. maybe I just used the wrong keywords 😉 Nevertheless IOctl(socket, FIONBIO, 1) does work.
At 13.08.2014 the second stage was ready to run, with the nonblocking socket calls.
It downloads nicely from two seeder at the same time. I had to tweek a little bit on both torrent client, set limits and so on to get this situation.
We have there:
192.168.0.238: Desktop where also AROS runs.
192.168.0.128: Windows Notebook with µTorrent
192.168.0.254: the server where also the tracker run and transmission.
As next I tried to go to a real torrent file with a real world tracker and seeder. I tried with some trackers and client at home at it works nicely. I’m rather sure that my client will not disturb other people in the bittorrent network with wrong packages or so.
But.. how to say… I did not work at all.. first, some hosts are just not available. And I made a non blocking call for the transfer but the connect was still blocking… So I reprogrammed it to a non blocking socket connect. (If you also want to do it: google for „socket connect timeout“). The principle is rather easy set the socket to nonblocking connect the socket and check with Select() (At AROS WaitSelect()) if the socket connects, there you can set a timeout. and also can make a loop to poll messageloop in between.
The second problem appears that some peers in the world, unchoke me, I send them some requests for packages and they never answer to them. I limited the maximum numbers for requests, hence after a while, my request queue was full of never answered requests (I waited and hour and nothing happend). I’m not sure whats the reason for this „not answering“ peers.
The solution is simple I just also brought a time out time for every request. I think later such things must be set in config or so.
In the beginning I wanted to use an AROS related torrent package, so I tried Icaros and Broadway torrents, but both do not work.. no seeders (I rechecked at my windows machine). I changed to debian iso torrent. (Many torrent files will not work, because I did not include multi file support, so atm the torrent MUST consist of a single file, besides this I only support HTTP trackers, so no UDP). But the debian ISO is fine, good tracker (the ubuntu tracker refuse my connect, I think because it does not know my PeerID Format), and many many seeds. Ok this was an other problem.. Of course more seeds is better but very inefficient as I noticed.. So I limited the number to 5 connections at a time. But then I had the problem that dead peers blocking my list and sometimes I have no peers to download… So i also implemented a refresh of peers, kick dead peers from the list and connect some new. At 14.08.2014, today.. was the day to run my client successfully in the wild on a real life torrent network:
There are some more things to notice:
- At the beginning it needs long time, looks like frozen, because he check the SHA1 of the file (which is already there and rather big, around 250MB) Later I will make a gui for it with progressbar or so.
- The file is already partial downloaded, I decided to use the same way as many other software so the partly downloaded get the extension „.part“, the sha1 check at start is used to determine which part still have to be downloaded
- In the beginning some peers are dead, later they are replaced with other peers and connected, with more peers the download runs rather nicely forward.
I’m already very happy about this result, even I’m still far away from a releaseable program. But it makes really fun to work with it.