From 58ad607c01e0189a43b7e41f5ca2fd9eeaefc17e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 19 Oct 2007 00:02:37 +0000 Subject: [PATCH] merge the wiki.theory.org, T, and libtorrent client lists. T knows about dozens more clients now. --- libtransmission/clients.c | 439 +++++++++++++++++++----------------- libtransmission/handshake.c | 8 +- 2 files changed, 232 insertions(+), 215 deletions(-) diff --git a/libtransmission/clients.c b/libtransmission/clients.c index 9e8466e41..abdd516e9 100644 --- a/libtransmission/clients.c +++ b/libtransmission/clients.c @@ -24,10 +24,15 @@ #include /* isprint */ #include +#include /* bsearch */ #include +#include /* event.h needs this */ +#include + #include "transmission.h" #include "trcompat.h" +#include "utils.h" /* tr_strdup */ static int charToInt( char character ) { @@ -42,181 +47,213 @@ static int charToInt( char character ) return value; } -char * tr_clientForId( const uint8_t * id ) +/* + * Azureus-style uses the following encoding: '-', two characters for client id, + * four ascii digits for version number, '-', followed by random numbers. + * For example: '-AZ2060-'... + */ + +struct az_client +{ + const char * abbreviation; + int version_width[4]; + const char * name; +}; + +static struct az_client azureus_clients[] = +{ + { "AG", { 1, 1, 1, 0 }, "Ares" }, + { "AR", { -1, -1, -1, -1 }, "Arctic Torrent" }, + { "AV", { -1, -1, -1, -1 }, "Avicora" }, + { "AX", { 2, 2, 0, 0 }, "BitPump" }, + { "AZ", { 1, 1, 1, 1 }, "Azureus" }, + { "A~", { 1, 1, 1, 0 }, "Ares" }, + { "BB", { 1, 3, 0, 0 }, "BitBuddy" }, + { "BC", { 2, 2, 0, 0 }, "BitComet" }, + { "BF", { -1, -1, -1, -1 }, "Bitflu" }, + { "BG", { 1, 1, 1, 1 }, "BTG" }, + { "BR", { 1, 1, 2, 0 }, "BitRocket" }, + { "BS", { -1, -1, -1, -1 }, "BTSlave" }, + { "BX", { -1, -1, -1, -1 }, "Bittorrent X" }, + { "CD", { 2, 2, 0, 0 }, "Enhanced CTorrent" }, + { "CT", { 1, 1, 2, 0 }, "CTorrent" }, + { "DE", { 1, 1, 1, 1 }, "DelugeTorrent" }, + { "DP", { -1, -1, -1, -1 }, "Propagate" }, + { "EB", { -1, -1, -1, -1 }, "EBit" }, + { "ES", { 1, 1, 1, 1 }, "Electric Sheep" }, + { "FT", { 4, 0, 0, 0 }, "FoxTorrent" }, + { "GR", { 1, 1, 1, 1 }, "GetRight" }, + { "GS", { 4, 0, 0, 0 }, "GSTorrent" }, + { "HL", { 1, 1, 1, 0 }, "Halite" }, + { "HN", { -1, -1, -1, -1 }, "Hydranode" }, + { "KT", { 1, 1, 1, 0 }, "KTorrent" }, + { "LH", { -1, -1, -1, -1 }, "LH-ABC" }, + { "LK", { -1, -1, -1, -1 }, "Linkage" }, + { "LP", { 2, 2, 0, 0 }, "Lphant" }, + { "LT", { 1, 1, 1, 1 }, "Libtorrent" }, + { "LW", { -1, -1, -1, -1 }, "LimeWire" }, + { "ML", { -1, -1, -1, -1 }, "MLDonkey" }, + { "MO", { -1, -1, -1, -1 }, "MonoTorrent" }, + { "MP", { -1, -1, -1, -1 }, "MooPolice" }, + { "MT", { -1, -1, -1, -1 }, "MoonlightTorrent" }, + { "PD", { 1, 1, 1, 1 }, "Pando" }, + { "QD", { -1, -1, -1, -1 }, "QQDownload" }, + { "QT", { -1, -1, -1, -1 }, "Qt 4 Torrent Example" }, + { "RT", { -1, -1, -1, -1 }, "Retriever" }, + { "SB", { -1, -1, -1, -1 }, "Swiftbit" }, + { "SN", { -1, -1, -1, -1 }, "ShareNet" }, + { "SS", { -1, -1, -1, -1 }, "SwarmScope" }, + { "ST", { -1, -1, -1, -1 }, "SymTorrent" }, + { "SZ", { 1, 1, 1, 1 }, "Shareaza" }, + { "S~", { 1, 1, 1, 1 }, "Shareaza (beta)" }, + { "TN", { -1, -1, -1, -1 }, "Torrent.Net" }, + { "TR", { 1, 2, 1, 0 }, "Transmission" }, + { "TS", { 1, 1, 1, 1 }, "TorrentStorm" }, + { "TT", { 1, 1, 1, 1 }, "TuoTu" }, + { "UL", { -1, -1, -1, -1 }, "uLeecher" }, + { "UT", { 1, 2, 0, 0 }, "uTorrent" }, + { "WT", { -1, -1, -1, -1 }, "BitLet" }, + { "WY", { -1, -1, -1, -1 }, "FireTorrent" }, + { "XL", { -1, -1, -1, -1 }, "Xunlei" }, + { "XT", { -1, -1, -1, -1 }, "XanTorrent" }, + { "XX", { 1, 1, 2, 0 }, "Xtorrent" }, + { "ZT", { -1, -1, -1, -1 }, "ZipTorrent" }, + { "lt", { 1, 1, 1, 1 }, "libTorrent" }, + { "qB", { 1, 1, 1, 0 }, "qBittorrent" }, + { "st", { -1, -1, -1, -1 }, "sharktorrent" } +}; + +static int +isStyleAzureus( const uint8_t * id ) +{ + return id[0]=='-' && id[7]=='-'; +} + +static char* +getAzureusAbbreviation( const uint8_t * id, char * setme ) +{ + setme[0] = id[1]; + setme[1] = id[2]; + setme[2] = '\0'; + return setme; +} + +static int +compareAzureusAbbreviations( const void * va, const void * vb ) +{ + const char * abbreviation = va; + const struct az_client * b = vb; + return strcmp( abbreviation, b->abbreviation ); +} + +static const struct az_client* +getAzureusClient( const uint8_t * peer_id ) +{ + const struct az_client * ret = NULL; + + if( isStyleAzureus( peer_id ) ) + { + char abbreviation[3]; + ret = bsearch( getAzureusAbbreviation( peer_id, abbreviation ), + azureus_clients, + sizeof(azureus_clients) / sizeof(azureus_clients[0]), + sizeof(struct az_client), + compareAzureusAbbreviations ); + } + + return ret; +} + + +struct generic_client +{ + int offset; + char const * id; + char const * name; +}; + +static struct generic_client generic_clients[] = +{ + { 0, "346-", "TorrentTopia" }, + { 0, "10-------", "JVtorrent" }, + { 0, "Deadman Walking-", "Deadman" }, + { 5, "Azureus", "Azureus 2.0.3.2" }, + { 0, "DansClient", "XanTorrent" }, + { 4, "btfans", "SimpleBT" }, + { 0, "eX", "eXeem" }, + { 0, "PRC.P---", "Bittorrent Plus! II" }, + { 0, "P87.P---", "Bittorrent Plus!" }, + { 0, "S587Plus", "Bittorrent Plus!" }, + { 0, "martini", "Martini Man" }, + { 0, "Plus---", "Bittorrent Plus" }, + { 0, "turbobt", "TurboBT" }, + { 0, "a00---0", "Swarmy" }, + { 0, "a02---0", "Swarmy" }, + { 0, "T00---0", "Teeweety" }, + { 0, "BTDWV-", "Deadman Walking" }, + { 2, "BS", "BitSpirit" }, + { 0, "Pando-", "Pando" }, + { 0, "LIME", "LimeWire" }, + { 0, "btuga", "BTugaXP" }, + { 0, "oernu", "BTugaXP" }, + { 0, "Mbrst", "Burst!" }, + { 0, "PEERAPP", "PeerApp" }, + { 0, "Plus", "Plus!" }, + { 0, "-Qt-", "Qt" }, + { 0, "exbc", "BitComet" }, + { 0, "DNA", "BitTorrent DNA" }, + { 0, "-G3", "G3 Torrent" }, + { 0, "-FG", "FlashGet" }, + { 0, "-ML", "MLdonkey" }, + { 0, "XBT", "XBT" }, + { 0, "OP", "Opera" }, + { 2, "RS", "Rufus" } +}; + +/*** +**** +***/ + +char* +tr_clientForId( const uint8_t * id ) { char * ret = NULL; - /* Azureus-style */ - if( id[0] == '-' && id[7] == '-' ) + if( isStyleAzureus( id ) ) { - if( !memcmp( &id[1], "TR", 2 ) ) + const struct az_client * client = getAzureusClient( id ); + + if( client != NULL ) { - /* support old-style Transmission id without maintenance number */ - if ( !memcmp( &id[3], "00", 2 ) ) - { - asprintf( &ret, "Transmission 0.%d", - charToInt( id[5] ) * 10 + charToInt( id[6] ) ); + struct evbuffer * buf = evbuffer_new( ); + + evbuffer_add_printf( buf, "%s ", client->name ); + + if( client->version_width[0] == -1 ) + evbuffer_add( buf, id+3, 4 ); + else { + int i, offset; + for( i=0, offset=3; i<4; ++i ) { + const int width = client->version_width[i]; + const int isdigit = isdigit( id[offset] ); + if( !width ) + break; + if( offset!=3 ) + evbuffer_add( buf, (isdigit?".":" "), 1 ); + if( !isdigit || width==1 || offset!=3 ) + evbuffer_add( buf, id+offset, width ); + else{ + char * tmp = tr_strndup( (char*)(id+offset), width ); + evbuffer_add_printf( buf, "%d", atoi(tmp) ); + tr_free( tmp ); + } + offset += width; + } } - else - { - asprintf( &ret, "Transmission %d.%c%c%s", - charToInt( id[3] ), id[4], id[5], - id[6] == 'Z' ? "+" : "" ); - } - } - else if( !memcmp( &id[1], "AZ", 2 ) ) - { - asprintf( &ret, "Azureus %c.%c.%c.%c", - id[3], id[4], id[5], id[6] ); - } - else if( !memcmp( &id[1], "UT", 2 ) ) - { - asprintf( &ret, "\xc2\xb5Torrent %c.%d", id[3], - charToInt( id[4] ) * 10 + charToInt( id[5] ) ); - } - else if( !memcmp( &id[1], "BC", 2 ) ) - { - asprintf( &ret, "BitComet %d.%c%c", - charToInt( id[3] ) * 10 + charToInt( id[4] ), - id[5], id[6] ); - } - else if( !memcmp( &id[1], "SZ", 2 ) || !memcmp( &id[1], "S~", 2 ) ) - { - asprintf( &ret, "Shareaza %c.%c.%c.%c", - id[3], id[4], id[5], id[6] ); - } - else if( !memcmp( &id[1], "BOW", 3 ) ) - { - if( !memcmp( &id[4], "A0C", 3 ) ) - { - asprintf( &ret, "Bits on Wheels 1.0.6" ); - } - else if( !memcmp( &id[4], "A0B", 3 ) ) - { - asprintf( &ret, "Bits on Wheels 1.0.5" ); - } - else - { - asprintf( &ret, "Bits on Wheels (%c%c%c)", - id[4], id[5], id[6] ); - } - } - else if( !memcmp( &id[1], "BR", 2 ) ) - { - asprintf( &ret, "BitRocket %c.%c (%d)", - id[3], id[4], charToInt( id[5] ) * 10 + charToInt( id[6] ) ); - } - else if( !memcmp( &id[1], "XX", 2 ) ) - { - asprintf( &ret, "Xtorrent %c.%c (%d)", - id[3], id[4], charToInt( id[5] ) * 10 + charToInt( id[6] ) ); - } - else if( !memcmp( &id[1], "TS", 2 ) ) - { - asprintf( &ret, "TorrentStorm %c.%c.%c.%c", - id[3], id[4], id[5], id[6] ); - } - else if( !memcmp( &id[1], "KT", 2 ) ) - { - if( id[5] == 'R' ) - { - asprintf( &ret, "KTorrent %c.%c RC %c", - id[3], id[4], id[6] ); - } - else if( id[5] == 'D' ) - { - asprintf( &ret, "KTorrent %c.%c Dev", - id[3], id[4] ); - } - else - { - asprintf( &ret, "KTorrent %c.%c.%c", - id[3], id[4], id[5] ); - } - } - else if( !memcmp( &id[1], "lt", 2 ) ) - { - asprintf( &ret, "libTorrent %d.%d.%d.%d", - charToInt( id[3] ), charToInt( id[4] ), - charToInt( id[5] ), charToInt( id[6] ) ); - } - else if( !memcmp( &id[1], "LT", 2 ) ) - { - asprintf( &ret, "libtorrent %d.%d.%d.%d", - charToInt( id[3] ), charToInt( id[4] ), - charToInt( id[5] ), charToInt( id[6] ) ); - } - else if( !memcmp( &id[1], "TT", 2 ) ) - { - asprintf( &ret, "TuoTu %c.%c.%c", - id[3], id[4], id[5] ); - } - else if( !memcmp( &id[1], "ES", 2 ) ) - { - asprintf( &ret, "Electric Sheep %c.%c.%c", - id[3], id[4], id[5] ); - } - else if( !memcmp( &id[1], "CD", 2 ) ) - { - asprintf( &ret, "Enhanced CTorrent %d.%d", - charToInt( id[3] ) * 10 + charToInt( id[4] ), - charToInt( id[5] ) * 10 + charToInt( id[6] ) ); - } - else if( !memcmp( &id[1], "CT", 2 ) ) - { - asprintf( &ret, "CTorrent %c.%c.%d", - id[3], id[4], - charToInt( id[5] ) * 10 + charToInt( id[6] ) ); - } - else if( !memcmp( &id[1], "LP", 2 ) ) - { - asprintf( &ret, "Lphant %d.%c%c", - charToInt( id[3] ) * 10 + charToInt( id[4] ), - id[5], id[6] ); - } - else if( !memcmp( &id[1], "AX", 2 ) ) - { - asprintf( &ret, "BitPump %d.%c%c", - charToInt( id[3] ) * 10 + charToInt( id[4] ), - id[5], id[6] ); - } - else if( !memcmp( &id[1], "DE", 2 ) ) - { - asprintf( &ret, "Deluge %d.%d.%d", - charToInt( id[3] ), charToInt( id[4] ), - charToInt( id[5] ) ); - } - else if( !memcmp( &id[1], "AG", 2 ) ) - { - asprintf( &ret, "Ares Galaxy %d.%d.%d", - charToInt( id[3] ), charToInt( id[4] ), - charToInt( id[5] ) ); - } - else if( !memcmp( &id[1], "HL", 2 ) ) - { - asprintf( &ret, "Halite %d.%d.%d", - charToInt( id[3] ), charToInt( id[4] ), - charToInt( id[5] ) ); - } - else if( !memcmp( &id[1], "AR", 2 ) ) - { - asprintf( &ret, "Arctic Torrent" ); - } - else if( !memcmp( &id[1], "BG", 2 ) ) - { - asprintf( &ret, "BTG %c.%c.%c.%c", - id[3], id[4], id[5], id[6] ); - } - else if( !memcmp( &id[1], "BB", 2 ) ) - { - asprintf( &ret, "BitBuddy %c.%c%c%c", - id[3], id[4], id[5], id[6] ); - } - else if( !memcmp( &id[1], "qB", 2 ) ) - { - asprintf( &ret, "qBittorrent %d.%d.%d", - charToInt( id[3] ), charToInt( id[4] ), - charToInt( id[5] ) ); + + evbuffer_add( buf, "\0", 1 ); + ret = tr_strdup( (char*) EVBUFFER_DATA( buf ) ); + evbuffer_free( buf ); } else if( !memcmp( &id[1], "BF", 2 ) ) { @@ -225,31 +262,35 @@ char * tr_clientForId( const uint8_t * id ) charToInt( id[4] ) * 10 + charToInt( id[5] ), charToInt( id[3] ) ); } - else if( !memcmp( &id[1], "FT", 2 ) ) + else if( !memcmp( &id[1], "BOW", 3 ) ) { - asprintf( &ret, "FoxTorrent (%c%c%c%c)", - id[3], id[4], id[5], id[6] ); + if( !memcmp( &id[4], "A0C", 3 ) ) + asprintf( &ret, "Bits on Wheels 1.0.6" ); + else if( !memcmp( &id[4], "A0B", 3 ) ) + asprintf( &ret, "Bits on Wheels 1.0.5" ); + else + asprintf( &ret, "Bits on Wheels (%3.3s", id+4 ); } - else if( !memcmp( &id[1], "GR", 2 ) ) - { - asprintf( &ret, "GetRight %c.%c.%c.%c", - id[3], id[4], id[5], id[6] ); - } - else if( !memcmp( &id[1], "PD", 2 ) ) - { - asprintf( &ret, "Pando %c.%c.%c.%c", - id[3], id[4], id[5], id[6] ); - } - else if( !memcmp( &id[1], "LW", 2 ) ) - { - asprintf( &ret, "LimeWire" ); - } - if( ret ) { +fprintf( stderr, "peer_id [%8.8s] returns [%s]\n", id, ret ); return ret; } } + + /* generic clients */ + { + int i; + const int n = sizeof(generic_clients) / sizeof(generic_clients[0]); + for( i=0; !ret && ioffset, client->id, strlen(client->id) ) ) + ret = tr_strdup( client->name ); + } + + if( ret ) + return ret; + } /* Tornado-style */ if( !memcmp( &id[4], "----", 4 ) || !memcmp( &id[4], "--0", 3 ) ) @@ -372,30 +413,6 @@ char * tr_clientForId( const uint8_t * id ) { asprintf( &ret, "Blizzard Downloader %d.%d", id[3] + 1, id[4] ); } - else if( !memcmp( id, "-WT-", 4 ) ) - { - asprintf( &ret, "BitLet" ); - } - else if( !memcmp( id, "LIME", 4 ) ) - { - asprintf( &ret, "LimeWire" ); - } - else if( !memcmp( id, "-G3", 3 ) ) - { - asprintf( &ret, "G3 Torrent" ); - } - else if( !memcmp( id, "10-------", 9 ) ) - { - asprintf( &ret, "JVtorrent" ); - } - else if( !memcmp( id, "346-", 4 ) ) - { - asprintf( &ret, "TorrentTopia" ); - } - else if( !memcmp( id, "eX", 2 ) ) - { - asprintf( &ret, "eXeem" ); - } else if( '\0' == id[0] && !memcmp( &id[1], "BS", 2 ) ) { asprintf( &ret, "BitSpirit %u", ( id[1] == 0 ? 1 : id[1] ) ); diff --git a/libtransmission/handshake.c b/libtransmission/handshake.c index abb699352..323b334ef 100644 --- a/libtransmission/handshake.c +++ b/libtransmission/handshake.c @@ -751,14 +751,14 @@ readCryptoProvide( tr_handshake * handshake, struct evbuffer * inbuf ) /* This next piece is HASH('req2', SKEY) xor HASH('req3', S) ... * we can get the first half of that (the obufscatedTorrentHash) * by building the latter and xor'ing it with what the peer sent us */ - dbgmsg( handshake, "reading obfuscated torrent hash...\n" ); + dbgmsg( handshake, "reading obfuscated torrent hash..." ); evbuffer_remove( inbuf, req2, SHA_DIGEST_LENGTH ); tr_sha1( req3, "req3", 4, handshake->mySecret, KEY_LEN, NULL ); for( i=0; ihandle, obfuscatedTorrentHash ); if( tor != NULL ) { - dbgmsg( handshake, "found the torrent; it's [%s]\n", tor->info.name ); + dbgmsg( handshake, "found the torrent; it's [%s]", tor->info.name ); tr_peerIoSetTorrentHash( handshake->io, tor->info.hash ); } else { dbgmsg( handshake, "can't find that torrent..." ); @@ -774,10 +774,10 @@ readCryptoProvide( tr_handshake * handshake, struct evbuffer * inbuf ) tr_peerIoReadUint32( handshake->io, inbuf, &crypto_provide ); handshake->crypto_provide = crypto_provide; - dbgmsg( handshake, "crypto_provide is %d\n", (int)crypto_provide ); + dbgmsg( handshake, "crypto_provide is %d", (int)crypto_provide ); tr_peerIoReadUint16( handshake->io, inbuf, &padc_len ); - dbgmsg( handshake, "padc is %d\n", (int)padc_len ); + dbgmsg( handshake, "padc is %d", (int)padc_len ); handshake->pad_c_len = padc_len; setState( handshake, AWAITING_PAD_C ); return READ_AGAIN;