RE: Re: QRP question (new Gnutella developer)

"Philippe Verdy" <[email protected]>
Newsgroups gmane.network.gnutella.devel
Organization Ordinateur Personnel
Message-ID <[email protected]>
> De : [email protected] [mailto:[email protected]] De la part
> de [email protected]
> Envoyé : mardi 4 septembre 2007 12:26
> À : [email protected]
> Objet : [the_gdf] Re: QRP question (new Gnutella developer)
> 
> Quoting mikeyv_b <[email protected]> from ml.gnutella.dev-forum:
> :So, here are my questions - I hope someone can help!
> :1. Do the message structures described in the second document match
> :the structures used in actual current QRP?
> 
> Yes, the QRP messages have not changed.
> 
> :2. I used these structures, and am having a problem. My client is not
> :reliably receiving searches from Phex, which I'm using as a host to
> :connect it to for testing.
> 
> Have you tried with gtk-gnutella as well?  You may have issues with
> internationalization and UTF-8 representations.  Gtk-gnutella has the
> correct algorithm implemented to compute the QRP hash value, especially
> in the presence of surrogates.  (this is not documented in the original
> LimeWire specs -- look at the qrp_hashcode() function in src/core/qrp.c
> for a correct C implementation).

For the case of surrogates, I had discussed this issue years ago, and had
described the problem in this list after discussing with a past Japanese
developer working at LimeWire (can't remember his name sorry) who worked
with me on making it international.

I had initially suggested a better way to handle non ISO-8859-1 characters
(because the default QRP hashing function discards all but the lowest 8 bits
of the UTF-16 code units.

But what should be known is that LimeWire internally handles all strings
using UTF-16 (not UTF-8) even if UTF-8 is used in encoded strings
transmitted on the network. This is important to understand because this
makes a big difference even with ISO-8859-1 only in the effective result of
the QRP hash function.

For characters out of the BMP (most often in the ideographic supplementary
plane), they are computed as if they were two surrogates, because of the
UTF-16 internal representation. This means that UTF-8 strings need to be
converted to UTF-16 for correct computing of the QRP hash function after
applying the NFKD substitution and removal of most diacritics and
simplification of spaces and punctuation.

I had wanted to change the way UTF-16 strings are used, so that it would not
ignore the 8 most significant bits of UTF-16 units, but would still preserve
the value of the computed QRP function for ISO-8859-1 only characters.
However this was not changed, and this causes bad indexing behaviour for
Japanese and Korean. The only change needed was to apply an OR to the low
and high byte of each UTF-16 code unit instead of just ignoring the high
byte, or some similar transform that preserves the computed value if the
high byte is null, but this would have needed to change the QRP table
content anyway (such change was applied in some third-party illegal clone of
LimeWire for Japanese, Korean and Chinese users, but not sourced back to
LimeWire because this clone was using LimeWire code without respecting the
GPL licence).

A revamped QRP hash function should be rediscussed now. It is possible to
preserve most of the compatibility with exisint QPR hash function so that it
will be mostly interoperable with legacy implementations for files shared
with Latin-written names.

The existing function works well for Latin, and other small alphabets that
can fit in a single 256-positions block (Arabic, Cyrillic, Greek), but it
fails miserably with large East-Asian scripts that span several 256-position
blocks (especially in Korean and Japanese), with too many collisions (and so
with poor QRP filtering). Preserving the interoperability for Arabic,
Hebrew, Cyrillic and Greek users would require handling some values for the
high bytes as if it was null. I suppose this can be done safely for all
values of high bytes (in UTF-16 code units) lower than 0x20.

My change was then:
* Read an UTF-16 code units into W;
* split W into high byte H and low byte L;
* if H < 0x20, set H := 0;
* use byte (L*(H*2+1)) instead of just L in the existing QRP function.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.