transmission 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ /******************************************************************************
2
+ * $Id: inout.h 346 2006-06-13 00:28:03Z 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_IO_H
26
+ #define TR_IO_H 1
27
+
28
+ typedef struct tr_io_s tr_io_t;
29
+
30
+ void tr_ioLoadResume ( tr_torrent_t * );
31
+
32
+ tr_io_t * tr_ioInit ( tr_torrent_t * );
33
+ int tr_ioRead ( tr_io_t *, int, int, int, uint8_t * );
34
+ int tr_ioWrite ( tr_io_t *, int, int, int, uint8_t * );
35
+ void tr_ioClose ( tr_io_t * );
36
+ void tr_ioSaveResume ( tr_io_t * );
37
+
38
+ #endif
@@ -0,0 +1,202 @@
1
+ /******************************************************************************
2
+ * $Id: internal.h 310 2006-06-09 19:53:35Z joshe $
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_INTERNAL_H
26
+ #define TR_INTERNAL_H 1
27
+
28
+ /* Standard headers used here and there.
29
+ That is probably ugly to put them all here, but it is sooo
30
+ convenient */
31
+ #include <stdio.h>
32
+ #include <stdarg.h>
33
+ #include <stdlib.h>
34
+ #include <string.h>
35
+ #include <unistd.h>
36
+ #include <errno.h>
37
+ #include <limits.h>
38
+ #include <signal.h>
39
+ #include <time.h>
40
+ #include <sys/time.h>
41
+ #include <sys/types.h>
42
+ #include <sys/stat.h>
43
+ #include <sys/resource.h>
44
+ #include <netdb.h>
45
+ #include <sys/socket.h>
46
+ #include <netinet/in.h>
47
+ #include <fcntl.h>
48
+ #include <assert.h>
49
+ #ifdef BEOS_NETSERVER
50
+ # define in_port_t uint16_t
51
+ #else
52
+ # include <arpa/inet.h>
53
+ #endif
54
+
55
+ #ifdef __GNUC__
56
+ # define UNUSED __attribute__((unused))
57
+ #else
58
+ # define UNUSED
59
+ #endif
60
+
61
+ /* We use OpenSSL whenever possible, since it is likely to be more
62
+ optimized and it is ok to use it with a MIT-licensed application.
63
+ Otherwise, we use the included implementation by vi@nwr.jp. */
64
+ #ifdef HAVE_OPENSSL
65
+ # undef SHA_DIGEST_LENGTH
66
+ # include <openssl/sha.h>
67
+ #else
68
+ # include "sha1.h"
69
+ # define SHA1(p,i,h) \
70
+ { \
71
+ sha1_state_s pms; \
72
+ sha1_init( &pms ); \
73
+ sha1_update( &pms, (sha1_byte_t *) p, i ); \
74
+ sha1_finish( &pms, (sha1_byte_t *) h ); \
75
+ }
76
+ #endif
77
+
78
+ /* Convenient macros to perform uint32_t endian conversions with
79
+ char pointers */
80
+ #define TR_NTOHL(p,a) (a) = tr_ntohl((p))
81
+ #define TR_HTONL(a,p) tr_htonl((a), (p))
82
+ static inline uint32_t tr_ntohl( uint8_t * p )
83
+ {
84
+ uint32_t u;
85
+ memcpy( &u, p, sizeof( uint32_t ) );
86
+ return ntohl( u );
87
+ }
88
+ static inline void tr_htonl( uint32_t a, uint8_t * p )
89
+ {
90
+ uint32_t u;
91
+ u = htonl( a );
92
+ memcpy ( p, &u, sizeof( uint32_t ) );
93
+ }
94
+
95
+ /* Sometimes the system defines MAX/MIN, sometimes not. In the latter
96
+ case, define those here since we will use them */
97
+ #ifndef MAX
98
+ #define MAX(a,b) ((a)>(b)?(a):(b))
99
+ #endif
100
+ #ifndef MIN
101
+ #define MIN(a,b) ((a)>(b)?(b):(a))
102
+ #endif
103
+
104
+ #define TR_MAX_PEER_COUNT 60
105
+
106
+ typedef struct tr_completion_s tr_completion_t;
107
+
108
+ #include "platform.h"
109
+ #include "bencode.h"
110
+ #include "metainfo.h"
111
+ #include "tracker.h"
112
+ #include "fdlimit.h"
113
+ #include "peer.h"
114
+ #include "net.h"
115
+ #include "inout.h"
116
+ #include "ratecontrol.h"
117
+ #include "clients.h"
118
+ #include "choking.h"
119
+
120
+ struct tr_torrent_s
121
+ {
122
+ tr_info_t info;
123
+
124
+ tr_ratecontrol_t * globalUpload;
125
+ tr_ratecontrol_t * globalDownload;
126
+ tr_ratecontrol_t * upload;
127
+ tr_ratecontrol_t * download;
128
+ tr_fd_t * fdlimit;
129
+
130
+ int status;
131
+ int error;
132
+ char trackerError[128];
133
+ int finished;
134
+
135
+ char * id;
136
+ char * key;
137
+ int * bindPort;
138
+
139
+ /* An escaped string used to include the hash in HTTP queries */
140
+ char hashString[3*SHA_DIGEST_LENGTH+1];
141
+
142
+ char scrape[MAX_PATH_LENGTH];
143
+
144
+ /* Where to download */
145
+ char * destination;
146
+
147
+ /* How many bytes we ask for per request */
148
+ int blockSize;
149
+ int blockCount;
150
+
151
+ tr_completion_t * completion;
152
+
153
+ volatile char die;
154
+ tr_thread_t thread;
155
+ tr_lock_t lock;
156
+
157
+ tr_tracker_t * tracker;
158
+ tr_io_t * io;
159
+ uint64_t stopDate;
160
+
161
+ int peerCount;
162
+ tr_peer_t * peers[TR_MAX_PEER_COUNT];
163
+
164
+ uint64_t date;
165
+ uint64_t downloaded;
166
+ uint64_t uploaded;
167
+
168
+ tr_stat_t stats[2];
169
+ int statCur;
170
+
171
+ tr_torrent_t * prev;
172
+ tr_torrent_t * next;
173
+ };
174
+
175
+ #include "utils.h"
176
+ #include "completion.h"
177
+
178
+ struct tr_handle_s
179
+ {
180
+ int torrentCount;
181
+ tr_torrent_t * torrentList;
182
+
183
+ tr_ratecontrol_t * upload;
184
+ tr_ratecontrol_t * download;
185
+ tr_fd_t * fdlimit;
186
+ tr_choking_t * choking;
187
+
188
+ int bindPort;
189
+ int bindSocket;
190
+
191
+ int acceptPeerCount;
192
+ tr_peer_t * acceptPeers[TR_MAX_PEER_COUNT];
193
+
194
+ char id[21];
195
+ char key[21];
196
+
197
+ volatile char acceptDie;
198
+ tr_thread_t acceptThread;
199
+ tr_lock_t acceptLock;
200
+ };
201
+
202
+ #endif
@@ -0,0 +1,339 @@
1
+ /******************************************************************************
2
+ * $Id: metainfo.c 405 2006-06-20 02:34:34Z 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
+ #include "transmission.h"
26
+
27
+ /***********************************************************************
28
+ * Local prototypes
29
+ **********************************************************************/
30
+ static void strcatUTF8( char *, char * );
31
+
32
+ /***********************************************************************
33
+ * tr_metainfoParse
34
+ ***********************************************************************
35
+ *
36
+ **********************************************************************/
37
+ int tr_metainfoParse( tr_info_t * inf, const char * path,
38
+ const char * savedHash, int saveCopy )
39
+ {
40
+ FILE * file;
41
+ char * buf;
42
+ benc_val_t meta, * beInfo, * list, * val;
43
+ char * s, * s2, * s3;
44
+ int i;
45
+ struct stat sb;
46
+
47
+ assert( NULL == path || NULL == savedHash );
48
+ /* if savedHash isn't null, saveCopy should be false */
49
+ assert( NULL == savedHash || !saveCopy );
50
+
51
+ if ( NULL != savedHash )
52
+ {
53
+ snprintf( inf->torrent, MAX_PATH_LENGTH, "%s/%s",
54
+ tr_getTorrentsDirectory(), savedHash );
55
+ path = inf->torrent;
56
+ }
57
+
58
+ if( stat( path, &sb ) )
59
+ {
60
+ /* fprintf( stderr, "Could not stat file (%s)\n", path );*/
61
+ return TR_PARSE_STAT;
62
+ }
63
+ if( ( sb.st_mode & S_IFMT ) != S_IFREG )
64
+ {
65
+ /* fprintf( stderr, "Not a regular file (%s)\n", path );*/
66
+ return TR_PARSE_FILE_TYPE;
67
+ }
68
+ if( sb.st_size > 2097152 )
69
+ {
70
+ /* tr_err( "Torrent file is too big (%d bytes)", sb.st_size );*/
71
+ return TR_PARSE_TOO_BIG;
72
+ }
73
+
74
+ /* Load the torrent file into our buffer */
75
+ file = fopen( path, "rb" );
76
+ if( !file )
77
+ {
78
+ /* fprintf( stderr, "Could not open file (%s)\n", path );*/
79
+ return TR_PARSE_FILE;
80
+ }
81
+ buf = malloc( sb.st_size );
82
+ fseek( file, 0, SEEK_SET );
83
+ if( fread( buf, sb.st_size, 1, file ) != 1 )
84
+ {
85
+ /* fprintf( stderr, "Read error (%s)\n", path );*/
86
+ free( buf );
87
+ fclose( file );
88
+ return TR_PARSE_READ;
89
+ }
90
+ fclose( file );
91
+
92
+ /* Parse bencoded infos */
93
+ if( tr_bencLoad( buf, sb.st_size, &meta, NULL ) )
94
+ {
95
+ /* fprintf( stderr, "Error while parsing bencoded data\n" );*/
96
+ free( buf );
97
+ return TR_PARSE_BENCODE;
98
+ }
99
+
100
+ /* Get info hash */
101
+ if( !( beInfo = tr_bencDictFind( &meta, "info" ) ) )
102
+ {
103
+ /* fprintf( stderr, "Could not find \"info\" dictionary\n" );*/
104
+ tr_bencFree( &meta );
105
+ free( buf );
106
+ return TR_PARSE_INFO_DIR;
107
+ }
108
+ SHA1( (uint8_t *) beInfo->begin,
109
+ (long) beInfo->end - (long) beInfo->begin, inf->hash );
110
+ for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
111
+ {
112
+ sprintf( inf->hashString + i * 2, "%02x", inf->hash[i] );
113
+ }
114
+
115
+ if( saveCopy )
116
+ {
117
+ /* Save a copy of the torrent file in the private torrent directory */
118
+ snprintf( inf->torrent, MAX_PATH_LENGTH, "%s/%s",
119
+ tr_getTorrentsDirectory(), inf->hashString );
120
+ file = fopen( inf->torrent, "wb" );
121
+ if( !file )
122
+ {
123
+ /* fprintf( stderr, "Could not open file (%s) (%s)\n", inf->torrent, strerror(errno) );*/
124
+ tr_bencFree( &meta );
125
+ free( buf );
126
+ return TR_PARSE_FILE;
127
+ }
128
+ fseek( file, 0, SEEK_SET );
129
+ if( fwrite( buf, sb.st_size, 1, file ) != 1 )
130
+ {
131
+ /* fprintf( stderr, "Write error (%s)\n", inf->torrent );*/
132
+ tr_bencFree( &meta );
133
+ free( buf );
134
+ fclose( file );
135
+ return TR_PARSE_WRITE;
136
+ }
137
+ fclose( file );
138
+ }
139
+ else
140
+ {
141
+ snprintf( inf->torrent, MAX_PATH_LENGTH, "%s", path );
142
+ }
143
+
144
+ /* We won't need this anymore */
145
+ free( buf );
146
+
147
+ if( !( val = tr_bencDictFind( &meta, "announce" ) ) )
148
+ {
149
+ /* fprintf( stderr, "No \"announce\" entry\n" );*/
150
+ tr_bencFree( &meta );
151
+ return TR_PARSE_ANN;
152
+ }
153
+
154
+ /* Skip spaces */
155
+ s3 = val->val.s.s;
156
+ while( *s3 && *s3 == ' ' )
157
+ {
158
+ s3++;
159
+ }
160
+
161
+ /* Parse announce URL */
162
+ if( strncmp( s3, "http://", 7 ) )
163
+ {
164
+ /* fprintf( stderr, "Invalid announce URL (%s)\n",
165
+ inf->trackerAddress );
166
+ */
167
+ tr_bencFree( &meta );
168
+ return TR_PARSE_ANN_URL;
169
+ }
170
+ s = strchr( s3 + 7, ':' );
171
+ s2 = strchr( s3 + 7, '/' );
172
+ if( s && s < s2 )
173
+ {
174
+ memcpy( inf->trackerAddress, s3 + 7,
175
+ (long) s - (long) s3 - 7 );
176
+ inf->trackerPort = atoi( s + 1 );
177
+ }
178
+ else if( s2 )
179
+ {
180
+ memcpy( inf->trackerAddress, s3 + 7,
181
+ (long) s2 - (long) s3 - 7 );
182
+ inf->trackerPort = 80;
183
+ }
184
+ else
185
+ {
186
+ /* fprintf( stderr, "Invalid announce URL (%s)\n",
187
+ inf->trackerAddress );*/
188
+ tr_bencFree( &meta );
189
+ return TR_PARSE_ANN_URL;
190
+ }
191
+ snprintf( inf->trackerAnnounce, MAX_PATH_LENGTH, "%s", s2 );
192
+
193
+ /* Piece length */
194
+ if( !( val = tr_bencDictFind( beInfo, "piece length" ) ) )
195
+ {
196
+ /* fprintf( stderr, "No \"piece length\" entry\n" );*/
197
+ tr_bencFree( &meta );
198
+ return TR_PARSE_PIECE;
199
+ }
200
+ inf->pieceSize = val->val.i;
201
+
202
+ /* Hashes */
203
+ val = tr_bencDictFind( beInfo, "pieces" );
204
+ if( val->val.s.i % SHA_DIGEST_LENGTH )
205
+ {
206
+ /* fprintf( stderr, "Invalid \"piece\" string (size is %d)\n",*/
207
+ /* val->val.s.i );*/
208
+ return TR_PARSE_PIECE;
209
+ }
210
+ inf->pieceCount = val->val.s.i / SHA_DIGEST_LENGTH;
211
+ inf->pieces = (uint8_t *) val->val.s.s; /* Ugly, but avoids a memcpy */
212
+ val->val.s.s = NULL;
213
+
214
+ /* TODO add more tests so we don't crash on weird files */
215
+
216
+ inf->totalSize = 0;
217
+ if( ( list = tr_bencDictFind( beInfo, "files" ) ) )
218
+ {
219
+ /* Multi-file mode */
220
+ int j;
221
+
222
+ val = tr_bencDictFind( beInfo, "name" );
223
+ strcatUTF8( inf->name, val->val.s.s );
224
+
225
+ inf->multifile = 1;
226
+ inf->fileCount = list->val.l.count;
227
+ inf->files = calloc( inf->fileCount * sizeof( tr_file_t ), 1 );
228
+
229
+ for( i = 0; i < list->val.l.count; i++ )
230
+ {
231
+ val = tr_bencDictFind( &list->val.l.vals[i], "path" );
232
+ strcatUTF8( inf->files[i].name, inf->name );
233
+ for( j = 0; j < val->val.l.count; j++ )
234
+ {
235
+ strcatUTF8( inf->files[i].name, "/" );
236
+ strcatUTF8( inf->files[i].name,
237
+ val->val.l.vals[j].val.s.s );
238
+ }
239
+ val = tr_bencDictFind( &list->val.l.vals[i], "length" );
240
+ inf->files[i].length = val->val.i;
241
+ inf->totalSize += val->val.i;
242
+ }
243
+
244
+ }
245
+ else
246
+ {
247
+ /* Single-file mode */
248
+ inf->multifile = 0;
249
+ inf->fileCount = 1;
250
+ inf->files = calloc( sizeof( tr_file_t ), 1 );
251
+
252
+ val = tr_bencDictFind( beInfo, "name" );
253
+ strcatUTF8( inf->files[0].name, val->val.s.s );
254
+ strcatUTF8( inf->name, val->val.s.s );
255
+
256
+ val = tr_bencDictFind( beInfo, "length" );
257
+ inf->files[0].length = val->val.i;
258
+ inf->totalSize += val->val.i;
259
+ }
260
+
261
+ if( (uint64_t) inf->pieceCount !=
262
+ ( inf->totalSize + inf->pieceSize - 1 ) / inf->pieceSize )
263
+ {
264
+ /* fprintf( stderr, "Size of hashes and files don't match\n" );*/
265
+ tr_bencFree( &meta );
266
+ return TR_PARSE_HASH;
267
+ }
268
+
269
+ tr_bencFree( &meta );
270
+ return 0;
271
+ }
272
+
273
+ void tr_metainfoRemoveSaved( const char * hashString )
274
+ {
275
+ char file[MAX_PATH_LENGTH];
276
+
277
+ snprintf( file, MAX_PATH_LENGTH, "%s/%s",
278
+ tr_getTorrentsDirectory(), hashString );
279
+ unlink(file);
280
+ }
281
+
282
+ /***********************************************************************
283
+ * strcatUTF8
284
+ ***********************************************************************
285
+ * According to the official specification, all strings in the torrent
286
+ * file are supposed to be UTF-8 encoded. However, there are
287
+ * non-compliant torrents around... If we encounter an invalid UTF-8
288
+ * character, we assume it is ISO 8859-1 and convert it to UTF-8.
289
+ **********************************************************************/
290
+ static void strcatUTF8( char * s, char * append )
291
+ {
292
+ char * p;
293
+
294
+ /* Go to the end of the destination string */
295
+ while( s[0] )
296
+ {
297
+ s++;
298
+ }
299
+
300
+ /* Now start appending, converting on the fly if necessary */
301
+ for( p = append; p[0]; )
302
+ {
303
+ if( !( p[0] & 0x80 ) )
304
+ {
305
+ /* ASCII character */
306
+ *(s++) = *(p++);
307
+ continue;
308
+ }
309
+
310
+ if( ( p[0] & 0xE0 ) == 0xC0 && ( p[1] & 0xC0 ) == 0x80 )
311
+ {
312
+ /* 2-bytes UTF-8 character */
313
+ *(s++) = *(p++); *(s++) = *(p++);
314
+ continue;
315
+ }
316
+
317
+ if( ( p[0] & 0xF0 ) == 0xE0 && ( p[1] & 0xC0 ) == 0x80 &&
318
+ ( p[2] & 0xC0 ) == 0x80 )
319
+ {
320
+ /* 3-bytes UTF-8 character */
321
+ *(s++) = *(p++); *(s++) = *(p++);
322
+ *(s++) = *(p++);
323
+ continue;
324
+ }
325
+
326
+ if( ( p[0] & 0xF8 ) == 0xF0 && ( p[1] & 0xC0 ) == 0x80 &&
327
+ ( p[2] & 0xC0 ) == 0x80 && ( p[3] & 0xC0 ) == 0x80 )
328
+ {
329
+ /* 4-bytes UTF-8 character */
330
+ *(s++) = *(p++); *(s++) = *(p++);
331
+ *(s++) = *(p++); *(s++) = *(p++);
332
+ continue;
333
+ }
334
+
335
+ /* ISO 8859-1 -> UTF-8 conversion */
336
+ *(s++) = 0xC0 | ( ( *p & 0xFF ) >> 6 );
337
+ *(s++) = 0x80 | ( *(p++) & 0x3F );
338
+ }
339
+ }