transmission 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }