source: trunk/libtransmission/clients.c @ 6795

Last change on this file since 6795 was 6795, checked in by charles, 13 years ago

run libT, cli, daemon, gtk through the source-code formatter "uncrustify" as promised/threatened

  • Property svn:keywords set to Date Rev Author Id
File size: 22.8 KB
Line 
1/*
2 * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: clients.c 6795 2008-09-23 19:11:04Z charles $
11 */
12
13/* thanks amc1! */
14
15#include <ctype.h> /* isprint, tolower */
16#include <stdio.h>
17#include <stdlib.h> /* strtol */
18#include <string.h>
19
20#include <libevent/event.h> /* evbuffer */
21
22#include "transmission.h"
23#include "clients.h"
24#include "utils.h"
25
26static int
27charint( char ch )
28{
29    if( '0' <= ch && ch <= '9' ) return ch - '0';
30    if( 'A' <= ch && ch <= 'Z' ) return 10 + ch - 'A';
31    if( 'a' <= ch && ch <= 'z' ) return 36 + ch - 'a';
32    return 0;
33}
34
35static int
36strint( const void * pch,
37        int          span )
38{
39    char tmp[64];
40
41    memcpy( tmp, pch, span );
42    tmp[span] = '\0';
43    return strtol( tmp, NULL, 0 );
44}
45
46static const char*
47getMnemonicEnd( char ch )
48{
49    switch( ch )
50    {
51        case 'b':
52        case 'B':
53            return " (Beta)";
54
55        case 'd':
56            return " (Debug)";
57
58        case 'x':
59        case 'X':
60        case 'Z':
61            return " (Dev)";
62
63        default:
64            return "";
65    }
66}
67
68static void
69three_digits( char *          buf,
70              size_t          buflen,
71              const char *    name,
72              const uint8_t * digits )
73{
74    tr_snprintf( buf, buflen, "%s %d.%d.%d", name,
75                charint( digits[0] ),
76                charint( digits[1] ),
77                charint( digits[2] ) );
78}
79
80static void
81four_digits( char *          buf,
82             size_t          buflen,
83             const char *    name,
84             const uint8_t * digits )
85{
86    tr_snprintf( buf, buflen, "%s %d.%d.%d.%d", name,
87                charint( digits[0] ),
88                charint( digits[1] ),
89                charint( digits[2] ),
90                charint( digits[3] ) );
91}
92
93static void
94two_major_two_minor( char *          buf,
95                     size_t          buflen,
96                     const char *    name,
97                     const uint8_t * digits )
98{
99    tr_snprintf( buf, buflen, "%s %d.%02d", name,
100                strint( digits, 2 ),
101                strint( digits + 2, 2 ) );
102}
103
104static void
105no_version( char *       buf,
106            size_t       buflen,
107            const char * name )
108{
109    tr_strlcpy( buf, name, buflen );
110}
111
112static void
113mainline_style( char *          buf,
114                size_t          buflen,
115                const char *    name,
116                const uint8_t * id )
117{
118    if( id[4] == '-' && id[6] == '-' )
119        tr_snprintf( buf, buflen, "%s %c.%c.%c", name, id[1], id[3], id[5] );
120    else if( id[5] == '-' )
121        tr_snprintf( buf, buflen, "%s %c.%c%c.%c", name, id[1], id[3],
122                     id[4],
123                     id[6] );
124}
125
126static int
127isMainlineStyle( const uint8_t * peer_id )
128{
129    /**
130     * One of the following styles will be used:
131     *   Mx-y-z--
132     *   Mx-yy-z-
133     */
134    return peer_id[2] == '-'
135           && peer_id[7] == '-'
136           && ( peer_id[4] == '-' || peer_id[5] == '-' );
137}
138
139static int
140decodeBitCometClient( char *          buf,
141                      size_t          buflen,
142                      const uint8_t * id )
143{
144    int          is_bitlord;
145    int          major, minor;
146    const char * name;
147    const char * mod = NULL;
148
149    if( !memcmp( id, "exbc", 4 ) ) mod = "";
150    else if( !memcmp( id, "FUTB", 4 ) ) mod = "(Solidox Mod) ";
151    else if( !memcmp( id, "xUTB", 4 ) ) mod = "(Mod 2) ";
152    else return FALSE;
153
154    is_bitlord = !memcmp( id + 6, "LORD", 4 );
155    name = ( is_bitlord ) ? "BitLord " : "BitComet ";
156    major = id[4];
157    minor = id[5];
158
159    /**
160     * Bitcomet, and older versions of BitLord, are of the form x.yy.
161     * Bitcoment 1.0 and onwards are of the form x.y.
162     */
163    if( is_bitlord && major > 0 )
164        tr_snprintf( buf, buflen, "%s%s%d.%d", name, mod, major, minor );
165    else
166        tr_snprintf( buf, buflen, "%s%s%d.%02d", name, mod, major, minor );
167
168    return TRUE;
169}
170
171static int
172decodeBitSpiritClient( char *          buf,
173                       size_t          buflen,
174                       const uint8_t * id )
175{
176    const int isBS = !memcmp( id + 2, "BS", 2 );
177
178    if( isBS )
179    {
180        const int version = id[1] ? id[1] : 1;
181        tr_snprintf( buf, buflen, "BitSpirit v%d", version );
182    }
183    return isBS;
184}
185
186void
187tr_clientForId( char *       buf,
188                size_t       buflen,
189                const void * id_in )
190{
191    const uint8_t * id = id_in;
192
193    *buf = '\0';
194
195    if( !id )
196        return;
197
198    /* Azureus-style */
199    if( id[0] == '-' && id[7] == '-' )
200    {
201        if( !memcmp( id + 1, "UT", 2 ) )
202        {
203            tr_snprintf( buf, buflen, "\xc2\xb5Torrent %d.%d.%d%s",
204                        strint( id + 3,
205                                1 ),
206                        strint( id + 4, 1 ), strint( id + 5,
207                                                     1 ),
208                        getMnemonicEnd( id[6] ) );
209        }
210        else if( !memcmp( id + 1, "TR", 2 ) )
211        {
212            if( !memcmp( id + 3, "000", 3 ) ) /* very old client style: -TR0006-
213                                                is 0.6 */
214                tr_snprintf( buf, buflen, "Transmission 0.%c", id[6] );
215            else if( !memcmp( id + 3, "00", 2 ) ) /* previous client style:
216                                                    -TR0072- is 0.72 */
217                tr_snprintf( buf, buflen, "Transmission 0.%02d",
218                            strint( id + 5, 2 ) );
219            else /* current client style: -TR111Z- is 1.11+ */
220                tr_snprintf( buf, buflen, "Transmission %d.%02d%s",
221                             strint( id + 3, 1 ), strint( id + 4, 2 ),
222                             id[6] == 'Z' || id[6] == 'X' ? "+" : "" );
223        }
224        else if( !memcmp( id + 1, "AZ", 2 ) )
225        {
226            if( id[3] > '3' || ( id[3] == '3' && id[4] >= '1' ) ) /* Vuze starts
227                                                                    at version
228                                                                    3.1.0.0 */
229                four_digits( buf, buflen, "Vuze", id + 3 );
230            else
231                four_digits( buf, buflen, "Azureus", id + 3 );
232        }
233        else if( !memcmp( id + 1, "KT", 2 ) )
234        {
235            if( id[5] == 'D' )
236                tr_snprintf( buf, buflen, "KTorrent %d.%d Dev %d",
237                            charint( id[3] ), charint( id[4] ),
238                            charint( id[6] ) );
239            else if( id[5] == 'R' )
240                tr_snprintf( buf, buflen, "KTorrent %d.%d RC %d",
241                            charint( id[3] ), charint( id[4] ),
242                            charint( id[6] ) );
243            else
244                three_digits( buf, buflen, "KTorrent", id + 3 );
245        }
246        else if( !memcmp( id + 1, "AR", 2 ) ) four_digits( buf, buflen,
247                                                           "Ares",
248                                                           id + 3 );
249        else if( !memcmp( id + 1, "AT", 2 ) ) four_digits( buf, buflen,
250                                                           "Artemis",
251                                                           id + 3 );
252        else if( !memcmp( id + 1, "AV", 2 ) ) four_digits( buf, buflen,
253                                                           "Avicora",
254                                                           id + 3 );
255        else if( !memcmp( id + 1, "BG", 2 ) ) four_digits( buf, buflen,
256                                                           "BTGetit",
257                                                           id + 3 );
258        else if( !memcmp( id + 1, "BM", 2 ) ) four_digits( buf, buflen,
259                                                           "BitMagnet",
260                                                           id + 3 );
261        else if( !memcmp( id + 1, "BX", 2 ) ) four_digits( buf, buflen,
262                                                           "BittorrentX",
263                                                           id + 3 );
264        else if( !memcmp( id + 1, "bk", 2 ) ) four_digits(
265                buf, buflen, "BitKitten (libtorrent)", id + 3 );
266        else if( !memcmp( id + 1, "BS", 2 ) ) four_digits( buf, buflen,
267                                                           "BTSlave",
268                                                           id + 3 );
269        else if( !memcmp( id + 1, "BX", 2 ) ) four_digits( buf, buflen,
270                                                           "BittorrentX",
271                                                           id + 3 );
272        else if( !memcmp( id + 1, "EB", 2 ) ) four_digits( buf, buflen,
273                                                           "EBit",
274                                                           id + 3 );
275        else if( !memcmp( id + 1, "DE", 2 ) ) four_digits( buf, buflen,
276                                                           "Deluge",
277                                                           id + 3 );
278        else if( !memcmp( id + 1, "DP", 2 ) ) four_digits(
279                buf, buflen, "Propogate Data Client", id + 3 );
280        else if( !memcmp( id + 1, "FC", 2 ) ) four_digits( buf, buflen,
281                                                           "FileCroc",
282                                                           id + 3 );
283        else if( !memcmp( id + 1, "FT", 2 ) ) four_digits(
284                buf, buflen, "FoxTorrent/RedSwoosh", id + 3 );
285        else if( !memcmp( id + 1, "GR", 2 ) ) four_digits( buf, buflen,
286                                                           "GetRight",
287                                                           id + 3 );
288        else if( !memcmp( id + 1, "HN", 2 ) ) four_digits( buf, buflen,
289                                                           "Hydranode",
290                                                           id + 3 );
291        else if( !memcmp( id + 1, "LH", 2 ) ) four_digits( buf, buflen,
292                                                           "LH-ABC",
293                                                           id + 3 );
294        else if( !memcmp( id + 1, "NX", 2 ) ) four_digits( buf, buflen,
295                                                           "Net Transport",
296                                                           id + 3 );
297        else if( !memcmp( id + 1, "MO", 2 ) ) four_digits( buf, buflen,
298                                                           "MonoTorrent",
299                                                           id + 3 );
300        else if( !memcmp( id + 1, "MR", 2 ) ) four_digits( buf, buflen,
301                                                           "Miro",
302                                                           id + 3 );
303        else if( !memcmp( id + 1, "MT", 2 ) ) four_digits( buf, buflen,
304                                                           "Moonlight",
305                                                           id + 3 );
306        else if( !memcmp( id + 1, "PD", 2 ) ) four_digits( buf, buflen,
307                                                           "Pando",
308                                                           id + 3 );
309        else if( !memcmp( id + 1, "RS", 2 ) ) four_digits( buf, buflen,
310                                                           "Rufus",
311                                                           id + 3 );
312        else if( !memcmp( id + 1, "RT", 2 ) ) four_digits( buf, buflen,
313                                                           "Retriever",
314                                                           id + 3 );
315        else if( !memcmp( id + 1, "SS", 2 ) ) four_digits( buf, buflen,
316                                                           "SwarmScope",
317                                                           id + 3 );
318        else if( !memcmp( id + 1, "SZ", 2 ) ) four_digits( buf, buflen,
319                                                           "Shareaza",
320                                                           id + 3 );
321        else if( !memcmp( id + 1, "S~", 2 ) ) four_digits( buf, buflen,
322                                                           "Shareaza",
323                                                           id + 3 );
324        else if( !memcmp( id + 1, "st", 2 ) ) four_digits( buf, buflen,
325                                                           "SharkTorrent",
326                                                           id + 3 );
327        else if( !memcmp( id + 1, "TN", 2 ) ) four_digits( buf, buflen,
328                                                           "Torrent .NET",
329                                                           id + 3 );
330        else if( !memcmp( id + 1, "TS", 2 ) ) four_digits( buf, buflen,
331                                                           "TorrentStorm",
332                                                           id + 3 );
333        else if( !memcmp( id + 1, "UL", 2 ) ) four_digits( buf, buflen,
334                                                           "uLeecher!",
335                                                           id + 3 );
336        else if( !memcmp( id + 1, "VG", 2 ) ) four_digits( buf, buflen,
337                                                           "Vagaa",
338                                                           id + 3 );
339        else if( !memcmp( id + 1, "WT", 2 ) ) four_digits( buf, buflen,
340                                                           "BitLet",
341                                                           id + 3 );
342        else if( !memcmp( id + 1, "WY", 2 ) ) four_digits( buf, buflen,
343                                                           "Wyzo",
344                                                           id + 3 );
345        else if( !memcmp( id + 1, "XL", 2 ) ) four_digits( buf, buflen,
346                                                           "Xunlei",
347                                                           id + 3 );
348        else if( !memcmp( id + 1, "XT", 2 ) ) four_digits( buf, buflen,
349                                                           "XanTorrent",
350                                                           id + 3 );
351        else if( !memcmp( id + 1, "ZT", 2 ) ) four_digits( buf, buflen,
352                                                           "Zip Torrent",
353                                                           id + 3 );
354
355        else if( !memcmp( id + 1, "AG", 2 ) ) three_digits( buf, buflen,
356                                                            "Ares",
357                                                            id + 3 );
358        else if( !memcmp( id + 1, "A~", 2 ) ) three_digits( buf, buflen,
359                                                            "Ares",
360                                                            id + 3 );
361        else if( !memcmp( id + 1, "ES", 2 ) ) three_digits(
362                buf, buflen, "Electric Sheep", id + 3 );
363        else if( !memcmp( id + 1, "HL", 2 ) ) three_digits( buf, buflen,
364                                                            "Halite",
365                                                            id + 3 );
366        else if( !memcmp( id + 1, "LT", 2 ) ) three_digits(
367                buf, buflen, "libtorrent (Rasterbar)", id + 3 );
368        else if( !memcmp( id + 1, "lt", 2 ) ) three_digits(
369                buf, buflen, "libTorrent (Rakshasa)", id + 3 );
370        else if( !memcmp( id + 1, "MP", 2 ) ) three_digits( buf, buflen,
371                                                            "MooPolice",
372                                                            id + 3 );
373        else if( !memcmp( id + 1, "TT", 2 ) ) three_digits( buf, buflen,
374                                                            "TuoTu",
375                                                            id + 3 );
376        else if( !memcmp( id + 1, "qB", 2 ) ) three_digits( buf, buflen,
377                                                            "qBittorrent",
378                                                            id + 3 );
379
380        else if( !memcmp( id + 1, "AX", 2 ) ) two_major_two_minor(
381                buf, buflen, "BitPump", id + 3 );
382        else if( !memcmp( id + 1, "BC", 2 ) ) two_major_two_minor(
383                buf, buflen, "BitComet", id + 3 );
384        else if( !memcmp( id + 1, "CD", 2 ) ) two_major_two_minor(
385                buf, buflen, "Enhanced CTorrent", id + 3 );
386        else if( !memcmp( id + 1, "LP", 2 ) ) two_major_two_minor( buf,
387                                                                   buflen,
388                                                                   "Lphant",
389                                                                   id + 3 );
390
391        else if( !memcmp( id + 1, "BF", 2 ) ) no_version( buf, buflen,
392                                                          "BitFlu" );
393        else if( !memcmp( id + 1, "LW", 2 ) ) no_version( buf, buflen,
394                                                          "LimeWire" );
395
396        else if( !memcmp( id + 1, "BB", 2 ) )
397        {
398            tr_snprintf( buf, buflen, "BitBuddy %c.%c%c%c", id[3], id[4],
399                         id[5],
400                         id[6] );
401        }
402        else if( !memcmp( id + 1, "BR", 2 ) )
403        {
404            tr_snprintf( buf, buflen, "BitRocket %c.%c (%c%c)", id[3],
405                         id[4], id[5],
406                         id[6] );
407        }
408        else if( !memcmp( id + 1, "CT", 2 ) )
409        {
410            tr_snprintf( buf, buflen, "CTorrent %d.%d.%02d", charint(
411                            id[3] ), charint( id[4] ), strint( id + 5, 2 ) );
412        }
413        else if( !memcmp( id + 1, "XX", 2 ) )
414        {
415            tr_snprintf( buf, buflen, "Xtorrent %d.%d (%d)", charint(
416                            id[3] ), charint( id[4] ), strint( id + 5, 2 ) );
417        }
418        else if( !memcmp( id + 1, "BOW", 3 ) )
419        {
420            if( !memcmp( &id[4], "A0B", 3 ) ) tr_snprintf(
421                    buf, buflen, "Bits on Wheels 1.0.5" );
422            else if( !memcmp( &id[4], "A0C", 3 ) ) tr_snprintf(
423                    buf, buflen, "Bits on Wheels 1.0.6" );
424            else tr_snprintf( buf, buflen, "Bits on Wheels %c.%c.%c", id[4],
425                              id[5],
426                              id[5] );
427        }
428
429        if( *buf )
430            return;
431    }
432
433    /* Shad0w-style */
434    if( !memcmp( &id[4], "----", 4 ) || !memcmp( &id[4], "--0", 3 ) )
435    {
436        switch( *id )
437        {
438            case 'A':
439                three_digits( buf, buflen, "ABC", id + 1 ); break;
440
441            case 'O':
442                three_digits( buf, buflen, "Osprey", id + 1 ); break;
443
444            case 'Q':
445                three_digits( buf, buflen, "BTQueue", id + 1 ); break;
446
447            case 'R':
448                three_digits( buf, buflen, "Tribler", id + 1 ); break;
449
450            case 'S':
451                three_digits( buf, buflen, "Shad0w", id + 1 ); break;
452
453            case 'T':
454                three_digits( buf, buflen, "BitTornado", id + 1 ); break;
455
456            default:
457                break;
458        }
459        if( *buf ) return;
460    }
461
462    /* Mainline */
463    if( isMainlineStyle( id ) )
464    {
465        if( *id == 'M' ) mainline_style( buf, buflen, "BitTorrent", id );
466        if( *id == 'Q' ) mainline_style( buf, buflen, "Queen Bee", id );
467        if( *buf ) return;
468    }
469
470    if( decodeBitCometClient( buf, buflen, id ) )
471        return;
472    if( decodeBitSpiritClient( buf, buflen, id ) )
473        return;
474
475    /* Clients with no version */
476    if( !memcmp( id, "AZ2500BT", 8 ) ) no_version(
477            buf, buflen, "BitTyrant (Azureus Mod)" );
478    else if( !memcmp( id, "LIME", 4 ) ) no_version( buf, buflen, "Limewire" );
479    else if( !memcmp( id, "martini", 7 ) ) no_version( buf, buflen,
480                                                       "Martini Man" );
481    else if( !memcmp( id, "Pando", 5 ) ) no_version( buf, buflen, "Pando" );
482    else if( !memcmp( id, "a00---0", 7 ) ) no_version( buf, buflen,
483                                                       "Swarmy" );
484    else if( !memcmp( id, "a02---0", 7 ) ) no_version( buf, buflen,
485                                                       "Swarmy" );
486    else if( !memcmp( id, "-G3", 3 ) ) no_version( buf, buflen,
487                                                   "G3 Torrent" );
488    else if( !memcmp( id, "10-------", 9 ) ) no_version( buf, buflen,
489                                                         "JVtorrent" );
490    else if( !memcmp( id, "346-", 4 ) ) no_version( buf, buflen,
491                                                    "TorrentTopia" );
492    else if( !memcmp( id, "eX", 2 ) ) no_version( buf, buflen, "eXeem" );
493    else if( !memcmp( id, "-FG", 3 ) ) two_major_two_minor( buf, buflen,
494                                                            "FlashGet",
495                                                            id + 3 );
496
497    /* Everything else */
498    else if( !memcmp( id, "S3",
499                      2 ) && id[2] == '-' && id[4] == '-' && id[6] == '-' )
500    {
501        tr_snprintf( buf, buflen, "Amazon S3 %c.%c.%c", id[3], id[5], id[7] );
502    }
503    else if( !memcmp( id, "OP", 2 ) )
504    {
505        tr_snprintf( buf, buflen, "Opera (Build %c%c%c%c)", id[2], id[3],
506                     id[4],
507                     id[5] );
508    }
509    else if( !memcmp( id, "-ML", 3 ) )
510    {
511        tr_snprintf( buf, buflen, "MLDonkey %c%c%c%c%c", id[3], id[4],
512                     id[5], id[6],
513                     id[7] );
514    }
515    else if( !memcmp( id, "DNA", 3 ) )
516    {
517        tr_snprintf( buf, buflen, "BitTorrent DNA %d.%d.%d",
518                    strint( id + 3, 2 ),
519                    strint( id + 5, 2 ),
520                    strint( id + 7, 2 ) );
521    }
522    else if( !memcmp( id, "Plus", 4 ) )
523    {
524        tr_snprintf( buf, buflen, "Plus! v2 %c.%c%c", id[4], id[5], id[6] );
525    }
526    else if( !memcmp( id, "XBT", 3 ) )
527    {
528        tr_snprintf( buf, buflen, "XBT Client %c.%c.%c%s", id[3], id[4],
529                    id[5], getMnemonicEnd(
530                        id[6] ) );
531    }
532    else if( !memcmp( id, "Mbrst", 5 ) )
533    {
534        tr_snprintf( buf, buflen, "burst! %c.%c.%c", id[5], id[7], id[9] );
535    }
536    else if( !memcmp( id, "btpd", 4 ) )
537    {
538        tr_snprintf( buf, buflen, "BT Protocol Daemon %c%c%c", id[5], id[6],
539                     id[7] );
540    }
541    else if( !memcmp( id, "BLZ", 3 ) )
542    {
543        tr_snprintf( buf, buflen, "Blizzard Downloader %d.%d", id[3] + 1,
544                     id[4] );
545    }
546    else if( '\0' == id[0] && !memcmp( &id[1], "BS", 2 ) )
547    {
548        tr_snprintf( buf, buflen, "BitSpirit %u", ( id[1] == 0 ? 1 : id[1] ) );
549    }
550
551    /* No match */
552    if( !*buf )
553    {
554        struct evbuffer * out = evbuffer_new( );
555        const char *      in, *in_end;
556        for( in = (const char*)id, in_end = in + 8; in != in_end; ++in )
557        {
558            if( isprint( *in ) )
559                evbuffer_add_printf( out, "%c", *in );
560            else
561                evbuffer_add_printf( out, "%%%02X", (unsigned int)*in );
562        }
563
564        tr_strlcpy( buf, EVBUFFER_DATA( out ), buflen );
565        evbuffer_free( out );
566    }
567}
568
Note: See TracBrowser for help on using the repository browser.