Hi Petr,
Yes, this was my first idea how to do it, however there is one major problem with QUrl encoding - it’s converting input data into utf-8 before they’re actually encoded, so instead of “%80″ I got “%C2%80″ etc (problem is with bytes with their ordinal value higher then 127, e.g. non-ascii). I haven’t found a way how to disable this “feature” so I had to implement data encoding and appending on my own.
The Qt docs state explicitly that a conversion to and from UTF-8 takes place. That even seems correct according to RFC-3986:
When a new URI scheme defines a component that represents textual
data consisting of characters from the Universal Character Set [UCS],
the data should first be encoded as octets according to the UTF-8
character encoding [STD63]; then only those octets that do not
correspond to characters in the unreserved set should be percent-
encoded. For example, the character A would be represented as “A”,
the character LATIN CAPITAL LETTER A WITH GRAVE would be represented
as “%C3%80″, and the character KATAKANA LETTER A would be represented
as “%E3%82%A2″.
I didn’t find any reference to UTF-8 in RFC-1738 but the query string component of the HTTP scheme should be text. But anyway, QUrl should have provided the option to pass non UTF-8 encoded data.
It would actually have been better if an base64 encoding of the hash had to be passed on to the tracker…
I was actually thinking about using URIs internally in Calitko for all kind of IDs or adresses. For example, NodeAddress could become a URI of the form “tcp:123.123.123.123:1234″, or “udp:…”. Then we could have a TransportFactory which returns a Transport object of the correct type. A similar approach could be useful also for Sessions.
I was thinking about using QUrl for that but maybe we could create our own class Uri. Initially I would just copy QUrl, rename it and add overloads taking QByteArray instead of QString (hope that would not require changing their internal representation). Then we could use class Uri also within the TorrentRequestWriter.
I’m pretty sure that using such a utility class would make the handling in TorrentRequestWriter much easier and would require less code. Let me experiment with Uri and I’ll give you feedback!
* I don’t have guaranted that the announce URL won’t contain “?” at the beginning (or do I? - haven’t found it in specs). For example, this could be a valid announce URL for me: http://tracker.com/announce.php?someparam=somevalue. This could mean that this particular tracker wants another parameter someparam to be set. So now I simply check what delimiter I should use and I put it there. See also the next reason.
* Now the calls don’t have to be in a specific order (ok, they should, because of tests, but lets forget it) because they just don’t need to be (info_hash could be the last parameter and “nothing happens”) and the delimiter is inserted at the beginning of the next parameter/argument, not at the end (in your example one should (but according to the rfc not necessarily) to omit the last ‘&’ - also see the 3rd reason) because of my appendArgumentDelimiter member function.
* Some of the arguments are only optional and in my case I can easily don’t append them because I test it in my append functions. I also need to “stringify” the argument and TorrentRequest doesn’t do it. This way I can also possibly check it’s validity (see my last comment in this post).
QUrl (or Uri) should be able to take care of all that in a transparent way.
* info_hash length (exactly 20B)
* peer_id length (exactly 20B)
* uploaded (can’t be
* downloaded (can’t be
* left (can’t be
* ip (if not valid then omit this parameter?)
* numwant (can’t be
* trackerid length (if not valid then omit this parameter?)
We could use types that enforce these requirements: InfoHash, RawPeerId, quin64. The ones that are nulls ( == T()) would be ignored and not appended.
Yes, that’s a good idea. It can simply calculate it from the input QByteArray. I was thinking about QCryptographicHash, but this class is available only in Qt 4.3 and I got only Qt 4.2 :(. Which Qt version should we use, anyway? I think I’ve read somewhere (calitko docs) that we should use only classes/functions that are in the 4.1 version, but I’m not sure.
I just haven’t updated this page and I think it said that at least 4.1 is required. Now that I’ve bundled patched versions of qmake and moc with calitko we are bound to a single minor release. I’ll need to merge qmake and moc from 3rdParty with the ones from Qt4.3 otherwise we might have problems compiling with Qt4.3. I haven’t actually tried so maybe it would work :-).
QCryptographicHash would help us with hashing but it simply returns the hash digest as a QByteArray. It might be nice if we had Sha1Digest, Md5Digest, etc. They could actually just be typedefs for instantiations of something like HashDigest
Regards,
Peter
