transmission 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,64 @@
1
+ /******************************************************************************
2
+ * $Id: bencode.h 261 2006-05-29 21:27:31Z titer $
3
+ *
4
+ * Copyright (c) 2005-2006 Transmission authors and contributors
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ * DEALINGS IN THE SOFTWARE.
23
+ *****************************************************************************/
24
+
25
+ #ifndef TR_BENCODE_H
26
+ #define TR_BENCODE_H 1
27
+
28
+ typedef struct benc_val_s
29
+ {
30
+ char * begin;
31
+ char * end;
32
+ #define TYPE_INT 1
33
+ #define TYPE_STR 2
34
+ #define TYPE_LIST 4
35
+ #define TYPE_DICT 8
36
+ char type;
37
+ union
38
+ {
39
+ int64_t i;
40
+ struct
41
+ {
42
+ int i;
43
+ char * s;
44
+ } s;
45
+ struct
46
+ {
47
+ int alloc;
48
+ int count;
49
+ struct benc_val_s * vals;
50
+ } l;
51
+ } val;
52
+ } benc_val_t;
53
+
54
+ #define tr_bencLoad(b,l,v,e) _tr_bencLoad((char*)(b),(l),(v),(char**)(e))
55
+ int _tr_bencLoad( char * buf, size_t len, benc_val_t * val,
56
+ char ** end );
57
+ void tr_bencPrint( benc_val_t * val );
58
+ void tr_bencFree( benc_val_t * val );
59
+ benc_val_t * tr_bencDictFind( benc_val_t * val, char * key );
60
+ char * tr_bencSaveMalloc( benc_val_t * val, size_t * len );
61
+ int tr_bencSave( benc_val_t * val, char ** buf,
62
+ size_t * used, size_t * max );
63
+
64
+ #endif
@@ -0,0 +1,335 @@
1
+ /******************************************************************************
2
+ * $Id: choking.c 261 2006-05-29 21:27:31Z titer $
3
+ *
4
+ * Copyright (c) 2006 Transmission authors and contributors
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ * DEALINGS IN THE SOFTWARE.
23
+ *****************************************************************************/
24
+
25
+ #include <math.h>
26
+ #include "transmission.h"
27
+
28
+ #ifndef HAVE_LRINTF
29
+ # define lrintf(a) ((int)(0.5+(a)))
30
+ #endif
31
+
32
+ /* We may try to allocate and free tables of size 0. Quick and dirty
33
+ way to handle it... */
34
+ void * __malloc( int size )
35
+ {
36
+ if( !size )
37
+ return NULL;
38
+ return malloc( size );
39
+ }
40
+ void __free( void * p )
41
+ {
42
+ if( p )
43
+ free( p );
44
+ }
45
+ #define malloc __malloc
46
+ #define free __free
47
+
48
+ struct tr_choking_s
49
+ {
50
+ tr_lock_t lock;
51
+ tr_handle_t * h;
52
+ int slots;
53
+ };
54
+
55
+ tr_choking_t * tr_chokingInit( tr_handle_t * h )
56
+ {
57
+ tr_choking_t * c;
58
+
59
+ c = calloc( sizeof( tr_choking_t ), 1 );
60
+ c->h = h;
61
+ c->slots = 4242;
62
+ tr_lockInit( &c->lock );
63
+
64
+ return c;
65
+ }
66
+
67
+ void tr_chokingSetLimit( tr_choking_t * c, int limit )
68
+ {
69
+ tr_lockLock( &c->lock );
70
+ if( limit < 0 )
71
+ c->slots = 4242;
72
+ else
73
+ /* Reckon a number of slots from the upload limit. There is no
74
+ official right way to do this, the formula below e.g. gives:
75
+ 10 KB/s -> 4 * 2.50 KB/s
76
+ 20 KB/s -> 6 * 3.33 KB/s
77
+ 50 KB/s -> 10 * 5.00 KB/s
78
+ 100 KB/s -> 14 * 7.14 KB/s */
79
+ c->slots = lrintf( sqrt( 2 * limit ) );
80
+ tr_lockUnlock( &c->lock );
81
+ }
82
+
83
+ #define sortPeersAscending(a,ac,z,zc,n,nc) sortPeers(a,ac,z,zc,n,nc,0)
84
+ #define sortPeersDescending(a,ac,z,zc,n,nc) sortPeers(a,ac,z,zc,n,nc,1)
85
+ static inline void sortPeers( tr_peer_t ** all, int allCount,
86
+ tr_peer_t ** zero, int * zeroCount,
87
+ tr_peer_t ** nonZero, int * nonZeroCount,
88
+ int order )
89
+ {
90
+ int i, shuffle;
91
+
92
+ /* Seperate uploaders from non-uploaders */
93
+ *zeroCount = 0;
94
+ *nonZeroCount = 0;
95
+ for( i = 0; i < allCount; i++ )
96
+ {
97
+ if( tr_peerDownloadRate( all[i] ) < 0.1 )
98
+ zero[(*zeroCount)++] = all[i];
99
+ else
100
+ nonZero[(*nonZeroCount)++] = all[i];
101
+ }
102
+
103
+ /* Randomly shuffle non-uploaders, so they are treated equally */
104
+ if( *zeroCount && ( shuffle = tr_rand( *zeroCount ) ) )
105
+ {
106
+ tr_peer_t ** bak;
107
+ bak = malloc( shuffle * sizeof( tr_peer_t * ) );
108
+ memcpy( bak, zero, shuffle * sizeof( tr_peer_t * ) );
109
+ memmove( zero, &zero[shuffle],
110
+ ( *zeroCount - shuffle ) * sizeof( tr_peer_t * ) );
111
+ memcpy( &zero[*zeroCount - shuffle], bak,
112
+ shuffle * sizeof( tr_peer_t * ) );
113
+ free( bak );
114
+ }
115
+
116
+ /* Sort uploaders by download rate */
117
+ for( i = *nonZeroCount - 1; i > 0; i-- )
118
+ {
119
+ float rate1, rate2;
120
+ tr_peer_t * tmp;
121
+ int j, sorted;
122
+
123
+ sorted = 1;
124
+ for( j = 0; j < i; j++ )
125
+ {
126
+ rate1 = tr_peerDownloadRate( nonZero[j] );
127
+ rate2 = tr_peerDownloadRate( nonZero[j+1] );
128
+ if( order ? ( rate1 < rate2 ) : ( rate1 > rate2 ) )
129
+ {
130
+ tmp = nonZero[j];
131
+ nonZero[j] = nonZero[j+1];
132
+ nonZero[j+1] = tmp;
133
+ sorted = 0;
134
+ }
135
+ }
136
+ if( sorted )
137
+ break;
138
+ }
139
+ }
140
+
141
+ void tr_chokingPulse( tr_choking_t * c )
142
+ {
143
+ int peersTotalCount, unchoked, mustOptimistic = 1;
144
+ tr_peer_t ** canChoke, ** canUnchoke;
145
+ tr_peer_t ** canChokeZero, ** canUnchokeZero;
146
+ tr_peer_t ** canChokeNonZero, ** canUnchokeNonZero;
147
+ int canChokeCount, canUnchokeCount;
148
+ int canChokeZeroCount, canUnchokeZeroCount;
149
+ int canChokeNonZeroCount, canUnchokeNonZeroCount;
150
+ tr_torrent_t * tor;
151
+ uint64_t now = tr_date();
152
+
153
+ tr_lockLock( &c->lock );
154
+
155
+ /* Lock all torrents and get the total number of peers */
156
+ peersTotalCount = 0;
157
+ for( tor = c->h->torrentList; tor; tor = tor->next )
158
+ {
159
+ tr_lockLock( &tor->lock );
160
+ peersTotalCount += tor->peerCount;
161
+ }
162
+
163
+ canChoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) );
164
+ canUnchoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) );
165
+ canChokeCount = 0;
166
+ canUnchokeCount = 0;
167
+ unchoked = 0;
168
+
169
+ for( tor = c->h->torrentList; tor; tor = tor->next )
170
+ {
171
+ tr_peer_t * peer;
172
+ int i;
173
+
174
+ for( i = 0; i < tor->peerCount; i++ )
175
+ {
176
+ peer = tor->peers[i];
177
+
178
+ if( !tr_peerIsConnected( peer ) )
179
+ continue;
180
+
181
+ /* Choke peers who have lost their interest in us */
182
+ if( !tr_peerIsInterested( peer ) )
183
+ {
184
+ if( tr_peerIsUnchoked( peer ) )
185
+ {
186
+ tr_peerChoke( peer );
187
+ tr_peerSetOptimistic( peer, 0 );
188
+ }
189
+ continue;
190
+ }
191
+
192
+ /* Build two lists of interested peers: those we may choke,
193
+ those we may unchoke. Whatever happens, we never choke a
194
+ peer less than 10 seconds after the time we unchoked him
195
+ (or the other way around). */
196
+ if( tr_peerIsUnchoked( peer ) )
197
+ {
198
+ if( tr_peerIsOptimistic( peer ) )
199
+ {
200
+ if( tr_peerLastChoke( peer ) + 30000 < now )
201
+ {
202
+ /* He got his 30 seconds, now we see him like
203
+ any other unchoked peer */
204
+ tr_peerSetOptimistic( peer, 0 );
205
+ }
206
+ else
207
+ {
208
+ /* Keep him unchoked for 30 seconds */
209
+ mustOptimistic = 0;
210
+ continue;
211
+ }
212
+ }
213
+
214
+ unchoked++;
215
+ if( tr_peerLastChoke( peer ) + 10000 < now )
216
+ canChoke[canChokeCount++] = peer;
217
+ }
218
+ else
219
+ {
220
+ if( tr_peerLastChoke( peer ) + 10000 < now )
221
+ canUnchoke[canUnchokeCount++] = peer;
222
+ }
223
+ }
224
+ }
225
+
226
+ canChokeZero = malloc( canChokeCount * sizeof( tr_peer_t * ) );
227
+ canChokeNonZero = malloc( canChokeCount * sizeof( tr_peer_t * ) );
228
+ canUnchokeZero = malloc( canUnchokeCount * sizeof( tr_peer_t * ) );
229
+ canUnchokeNonZero = malloc( canUnchokeCount * sizeof( tr_peer_t * ) );
230
+
231
+ sortPeersDescending( canChoke, canChokeCount,
232
+ canChokeZero, &canChokeZeroCount,
233
+ canChokeNonZero, &canChokeNonZeroCount);
234
+ sortPeersAscending( canUnchoke, canUnchokeCount,
235
+ canUnchokeZero, &canUnchokeZeroCount,
236
+ canUnchokeNonZero, &canUnchokeNonZeroCount);
237
+
238
+ free( canChoke );
239
+ free( canUnchoke );
240
+
241
+ if( mustOptimistic )
242
+ {
243
+ tr_peer_t * peer;
244
+
245
+ /* Open an extra slot for optimistic choking */
246
+ if( canUnchokeZeroCount )
247
+ {
248
+ /* TODO: prefer peers with no pieces at all */
249
+ peer = canUnchokeZero[--canUnchokeZeroCount];
250
+ tr_peerUnchoke( peer );
251
+ tr_peerSetOptimistic( peer, 1 );
252
+ }
253
+ else if( canUnchokeNonZeroCount )
254
+ {
255
+ peer = canUnchokeNonZero[--canUnchokeNonZeroCount];
256
+ tr_peerUnchoke( peer );
257
+ tr_peerSetOptimistic( peer, 1 );
258
+ }
259
+ }
260
+
261
+ /* If we have more open slots than what we should have (the user has
262
+ just lowered his upload limit), we need to choke some of the
263
+ peers we are uploading to. We start with the peers who aren't
264
+ uploading to us, then those we upload the least. */
265
+ while( unchoked > c->slots && canChokeZeroCount > 0 )
266
+ {
267
+ tr_peerChoke( canChokeZero[--canChokeZeroCount] );
268
+ unchoked--;
269
+ }
270
+ while( unchoked > c->slots && canChokeNonZeroCount > 0 )
271
+ {
272
+ tr_peerChoke( canChokeNonZero[--canChokeNonZeroCount] );
273
+ unchoked--;
274
+ }
275
+
276
+ /* If we have unused open slots, let's unchoke some people. We start
277
+ with the peers who are uploading to us the most. */
278
+ while( unchoked < c->slots && canUnchokeNonZeroCount > 0 )
279
+ {
280
+ tr_peerUnchoke( canUnchokeNonZero[--canUnchokeNonZeroCount] );
281
+ unchoked++;
282
+ }
283
+ while( unchoked < c->slots && canUnchokeZeroCount > 0 )
284
+ {
285
+ tr_peerUnchoke( canUnchokeZero[--canUnchokeZeroCount] );
286
+ unchoked++;
287
+ }
288
+
289
+ /* Choke peers who aren't uploading if there are good peers waiting
290
+ for an unchoke */
291
+ while( canChokeZeroCount > 0 && canUnchokeNonZeroCount > 0 )
292
+ {
293
+ tr_peerChoke( canChokeZero[--canChokeZeroCount] );
294
+ tr_peerUnchoke( canUnchokeNonZero[--canUnchokeNonZeroCount] );
295
+ }
296
+
297
+ /* Choke peers who aren't uploading that much if there are choked
298
+ peers who are uploading more */
299
+ while( canChokeNonZeroCount > 0 && canUnchokeNonZeroCount > 0 )
300
+ {
301
+ if( tr_peerDownloadRate( canUnchokeNonZero[canUnchokeNonZeroCount - 1] )
302
+ < tr_peerDownloadRate( canChokeNonZero[canChokeNonZeroCount - 1] ) )
303
+ break;
304
+
305
+ tr_peerChoke( canChokeNonZero[--canChokeNonZeroCount] );
306
+ tr_peerUnchoke( canUnchokeNonZero[--canUnchokeNonZeroCount] );
307
+ }
308
+
309
+ /* Some unchoked peers still aren't uploading to us, let's give a
310
+ chance to other non-uploaders */
311
+ while( canChokeZeroCount > 0 && canUnchokeZeroCount > 0 )
312
+ {
313
+ tr_peerChoke( canChokeZero[--canChokeZeroCount] );
314
+ tr_peerUnchoke( canUnchokeZero[--canUnchokeZeroCount] );
315
+ }
316
+
317
+ free( canChokeZero );
318
+ free( canChokeNonZero );
319
+ free( canUnchokeZero );
320
+ free( canUnchokeNonZero );
321
+
322
+ /* Unlock all torrents */
323
+ for( tor = c->h->torrentList; tor; tor = tor->next )
324
+ {
325
+ tr_lockUnlock( &tor->lock );
326
+ }
327
+
328
+ tr_lockUnlock( &c->lock );
329
+ }
330
+
331
+ void tr_chokingClose( tr_choking_t * c )
332
+ {
333
+ tr_lockClose( &c->lock );
334
+ free( c );
335
+ }
@@ -0,0 +1,30 @@
1
+ /******************************************************************************
2
+ * $Id: choking.h 261 2006-05-29 21:27:31Z titer $
3
+ *
4
+ * Copyright (c) 2006 Transmission authors and contributors
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ * DEALINGS IN THE SOFTWARE.
23
+ *****************************************************************************/
24
+
25
+ typedef struct tr_choking_s tr_choking_t;
26
+
27
+ tr_choking_t * tr_chokingInit( tr_handle_t * );
28
+ void tr_chokingSetLimit( tr_choking_t *, int );
29
+ void tr_chokingPulse( tr_choking_t * );
30
+ void tr_chokingClose( tr_choking_t * );
@@ -0,0 +1,90 @@
1
+ /******************************************************************************
2
+ * $Id: clients.c 261 2006-05-29 21:27:31Z titer $
3
+ *
4
+ * Copyright (c) 2005 Transmission authors and contributors
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ * DEALINGS IN THE SOFTWARE.
23
+ *****************************************************************************/
24
+
25
+ #include "transmission.h"
26
+
27
+ char * tr_clientForId( uint8_t * id )
28
+ {
29
+ char * ret = NULL;
30
+
31
+ if( id[0] == '-' && id[7] == '-' )
32
+ {
33
+ if( !memcmp( &id[1], "TR", 2 ) )
34
+ {
35
+ asprintf( &ret, "Transmission %d.%d",
36
+ ( id[3] - '0' ) * 10 + ( id[4] - '0' ),
37
+ ( id[5] - '0' ) * 10 + ( id[6] - '0' ) );
38
+ }
39
+ else if( !memcmp( &id[1], "AZ", 2 ) )
40
+ {
41
+ asprintf( &ret, "Azureus %c.%c.%c.%c",
42
+ id[3], id[4], id[5], id[6] );
43
+ }
44
+ else if( !memcmp( &id[1], "TS", 2 ) )
45
+ {
46
+ asprintf( &ret, "TorrentStorm (%c%c%c%c)",
47
+ id[3], id[4], id[5], id[6] );
48
+ }
49
+ else if( !memcmp( &id[1], "BC", 2 ) )
50
+ {
51
+ asprintf( &ret, "BitComet %d.%c%c",
52
+ ( id[3] - '0' ) * 10 + ( id[4] - '0' ),
53
+ id[5], id[6] );
54
+ }
55
+ else if( !memcmp( &id[1], "SZ", 2 ) )
56
+ {
57
+ asprintf( &ret, "Shareaza %c.%c.%c.%c",
58
+ id[3], id[4], id[5], id[6] );
59
+ }
60
+ }
61
+ else if( !memcmp( &id[4], "----", 4 ) )
62
+ {
63
+ if( id[0] == 'T' )
64
+ {
65
+ asprintf( &ret, "BitTornado (%c%c%c)", id[1], id[2], id[3] );
66
+ }
67
+ else if( id[0] == 'A' )
68
+ {
69
+ asprintf( &ret, "ABC (%c%c%c)", id[1], id[2], id[3] );
70
+ }
71
+ }
72
+ else if( id[0] == 'M' && id[2] == '-' &&
73
+ id[4] == '-' && id[6] == '-' &&
74
+ id[7] == '-' )
75
+ {
76
+ asprintf( &ret, "BitTorrent %c.%c.%c", id[1], id[3], id[5] );
77
+ }
78
+ else if( !memcmp( id, "exbc", 4 ) )
79
+ {
80
+ asprintf( &ret, "BitComet %d.%02d", id[4], id[5] );
81
+ }
82
+
83
+ if( !ret )
84
+ {
85
+ asprintf( &ret, "Unknown client (%c%c%c%c%c%c%c%c)",
86
+ id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7] );
87
+ }
88
+
89
+ return ret;
90
+ }