First BitTorrent Steps

Today I was working on BitTorrent packets. There is a class BitTorrent::Packets::Packet which is derived from Generics::Packet and implements some tasks common to all BitTorrent packets. It takes care of reading and writing the header and leaves the corresponding payload functions pure virtual, so that all concrete BitTorrent classes are forced to implement them.

Interesting here was my observation regarding the trailer related functions. I was concerned about adding trailer functions without having a packet that would use it. I wouldn’t want to add a solution to a yet unknown problem because the result could be overhead and additional support for something that might turn out to be inadequate. Anyway, I was with BitTorrent that it is just enough to implement empty readTrailer() and writeTrailer() functions, so the overhead is very little. Additionally, I thought about adequateness and concluded that a trailer should not be too different from a header, so using a similar abstraction should be adequate. A question to answer in the future remains: in which order should header, payload and trailer be generated (using the writeX functions)? I already know that the header should be generated after the payload because normally the header contains the length of the payload. It would be logical to generate the trailer after the payload and probably also after the header (the trailer could contain a checksum of header + payload). Any condition like this should be enforced in rawTrailer() and it has been done in rawHeader().

Now, there is a total of ten packets described in the BitTorrent specs. Five of these have not payload. This means their implementation would be almost identical. The only difference would be the value that name() should return and the PacketType value that needs to be passed to the ctor of the base. One solution would be to use a single class for all five packet types but I do not like this option. With it we wouldn’t be able to use Atul’s great idea to utilize the visitor pattern for packets. For visitor to work, we need a class per packet. Then I thought about the other option – templates.

SimplePacket is a template class that takes a single non-type template value (PacketType). All packets with no payload are simply typedefs of a SimplePacket instantiation! For each instantiation additionally a const static member specifying the name returned by name() must be specified and that’s all! I tried to pass the packet name as a template argument but that didn’t work. Non-type template arguments (const values) can be passes only if they are of numeric type. This means ints, floats, enums, but not QString or const char *.

BasicRequest is also a template class from which Request and Cancel are instantiated. I was wondering whether templates could be further exploited in order to spare us writing some code (I think that’s termed metaprogramming). Any suggestions how to do that?

BitTorrent packets do not implement reference counting on the private data. I’m wondering how to push reference counting completely to the base class Generics::Packet. A solution would be to have the derived classes derive their private data from the private data of their superclass (you could see that in action in the source of Qt). Any other ideas?

I’ll probably let my unconsciousness do some work on the background for a day or two before I continue working on BitTorrent packets. I hope in the meantime some of come with interesting observations or ideas and share them here for the sake of a better solution ;-).

Regards,

Peter

P.S. This patch is based on revno 66 and is NOT committed yet. It will not be committed until we have some discussion about the implementation and approve it here.

To get revno 66 and apply the patch, do this:


$ bzr branch http://bzr.calitko.org/calitko calitko-0.5.5-BitTorrent -r 66
$ cd calitko-0.5.5-BitTorrent
$ patch –p0 < ../calitko-0.5.5-BitTorrent.patch
$ qmake
$ make

Attached Files:

Would you like to post a relpy?


This post starts a thread.
No follow-ups yet.