transmission 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,55 @@
1
+ /******************************************************************************
2
+ * $Id: peer.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_PEER_H
26
+ #define TR_PEER_H 1
27
+
28
+ typedef struct tr_peer_s tr_peer_t;
29
+
30
+ void tr_peerAddOld ( tr_torrent_t *, char *, int );
31
+ void tr_peerAddCompact ( tr_torrent_t *, struct in_addr, in_port_t );
32
+ tr_peer_t * tr_peerInit ( struct in_addr, in_port_t, int );
33
+ void tr_peerAttach ( tr_torrent_t *, tr_peer_t * );
34
+ void tr_peerDestroy ( tr_fd_t *, tr_peer_t * );
35
+ void tr_peerRem ( tr_torrent_t *, int );
36
+ int tr_peerRead ( tr_torrent_t *, tr_peer_t * );
37
+ uint64_t tr_peerDate ( tr_peer_t * );
38
+ uint8_t * tr_peerHash ( tr_peer_t * );
39
+ void tr_peerPulse ( tr_torrent_t * );
40
+ int tr_peerIsConnected ( tr_peer_t * );
41
+ int tr_peerIsUploading ( tr_peer_t * );
42
+ int tr_peerIsDownloading ( tr_peer_t * );
43
+ uint8_t * tr_peerBitfield ( tr_peer_t * );
44
+ float tr_peerDownloadRate ( tr_peer_t * );
45
+ int tr_peerIsUnchoked ( tr_peer_t * );
46
+ int tr_peerIsInterested ( tr_peer_t * );
47
+ void tr_peerChoke ( tr_peer_t * );
48
+ void tr_peerUnchoke ( tr_peer_t * );
49
+ uint64_t tr_peerLastChoke ( tr_peer_t * );
50
+ void tr_peerSetOptimistic ( tr_peer_t *, int );
51
+ int tr_peerIsOptimistic ( tr_peer_t * );
52
+ void tr_peerBlame ( tr_torrent_t *, tr_peer_t *,
53
+ int piece, int success );
54
+
55
+ #endif
@@ -0,0 +1,326 @@
1
+ /******************************************************************************
2
+ * $Id: peermessages.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
+ /***********************************************************************
26
+ * This file handles all outgoing messages
27
+ **********************************************************************/
28
+
29
+ static uint8_t * messagesPending( tr_peer_t * peer, int * size )
30
+ {
31
+ if( peer->outBlockSending || peer->outMessagesPos < 1 )
32
+ {
33
+ return NULL;
34
+ }
35
+
36
+ *size = MIN( peer->outMessagesPos, 1024 );
37
+
38
+ return peer->outMessages;
39
+ }
40
+
41
+ static void messagesSent( tr_peer_t * peer, int size )
42
+ {
43
+ peer->outMessagesPos -= size;
44
+ memmove( peer->outMessages, &peer->outMessages[size],
45
+ peer->outMessagesPos );
46
+ }
47
+
48
+ static uint8_t * blockPending( tr_torrent_t * tor, tr_peer_t * peer,
49
+ int * size )
50
+ {
51
+ if( !peer->outBlockLoaded )
52
+ {
53
+ uint8_t * p;
54
+ tr_request_t * r;
55
+
56
+ if( peer->amChoking || peer->outRequestCount < 1 )
57
+ {
58
+ /* No piece to send */
59
+ return NULL;
60
+ }
61
+
62
+ /* We need to load the block for the next request */
63
+ r = &peer->outRequests[0];
64
+
65
+ /* Sanity check */
66
+ if( !tr_cpPieceIsComplete( tor->completion, r->index ) )
67
+ {
68
+ /* We have been asked for something we don't have, buggy client?
69
+ Let's just drop this request */
70
+ tr_inf( "Block %d/%d/%d was requested but we don't have it",
71
+ r->index, r->begin, r->length );
72
+ (peer->outRequestCount)--;
73
+ memmove( &peer->outRequests[0], &peer->outRequests[1],
74
+ peer->outRequestCount * sizeof( tr_request_t ) );
75
+ return NULL;
76
+ }
77
+
78
+ p = (uint8_t *) peer->outBlock;
79
+
80
+ TR_HTONL( 9 + r->length, p );
81
+ p[4] = 7;
82
+ TR_HTONL( r->index, p + 5 );
83
+ TR_HTONL( r->begin, p + 9 );
84
+
85
+ tr_ioRead( tor->io, r->index, r->begin, r->length, &p[13] );
86
+
87
+ peer_dbg( "SEND piece %d/%d (%d bytes)",
88
+ r->index, r->begin, r->length );
89
+
90
+ peer->outBlockSize = 13 + r->length;
91
+ peer->outBlockLoaded = 1;
92
+
93
+ (peer->outRequestCount)--;
94
+ memmove( &peer->outRequests[0], &peer->outRequests[1],
95
+ peer->outRequestCount * sizeof( tr_request_t ) );
96
+ }
97
+
98
+ *size = MIN( 1024, peer->outBlockSize );
99
+
100
+ return (uint8_t *) peer->outBlock;
101
+ }
102
+
103
+ static void blockSent( tr_peer_t * peer, int size )
104
+ {
105
+ peer->outBlockSize -= size;
106
+ memmove( peer->outBlock, &peer->outBlock[size], peer->outBlockSize );
107
+
108
+ if( peer->outBlockSize > 0 )
109
+ {
110
+ /* We can't send messages until we are done sending the block */
111
+ peer->outBlockSending = 1;
112
+ }
113
+ else
114
+ {
115
+ /* Block fully sent */
116
+ peer->outBlockSending = 0;
117
+ peer->outBlockLoaded = 0;
118
+ }
119
+ }
120
+
121
+ static uint8_t * getPointerForSize( tr_peer_t * peer, int size )
122
+ {
123
+ uint8_t * p;
124
+
125
+ if( peer->outMessagesPos + size > peer->outMessagesSize )
126
+ {
127
+ peer->outMessagesSize = peer->outMessagesPos + size;
128
+ peer->outMessages = realloc( peer->outMessages,
129
+ peer->outMessagesSize );
130
+ }
131
+
132
+ p = &peer->outMessages[peer->outMessagesPos];
133
+ peer->outMessagesPos += size;
134
+
135
+ return p;
136
+ }
137
+
138
+ /***********************************************************************
139
+ * sendKeepAlive
140
+ ***********************************************************************
141
+ *
142
+ **********************************************************************/
143
+ static void sendKeepAlive( tr_peer_t * peer )
144
+ {
145
+ uint8_t * p;
146
+
147
+ p = getPointerForSize( peer, 4 );
148
+
149
+ TR_HTONL( 0, p );
150
+
151
+ peer_dbg( "SEND keep-alive" );
152
+ }
153
+
154
+
155
+ /***********************************************************************
156
+ * sendChoke
157
+ ***********************************************************************
158
+ *
159
+ **********************************************************************/
160
+ static void sendChoke( tr_peer_t * peer, int yes )
161
+ {
162
+ uint8_t * p;
163
+
164
+ p = getPointerForSize( peer, 5 );
165
+
166
+ TR_HTONL( 1, p );
167
+ p[4] = yes ? 0 : 1;
168
+
169
+ peer->amChoking = yes;
170
+
171
+ if( !yes )
172
+ {
173
+ /* Drop older requests from the last time it was unchoked,
174
+ if any */
175
+ peer->outRequestCount = 0;
176
+ }
177
+
178
+ peer_dbg( "SEND %schoke", yes ? "" : "un" );
179
+ }
180
+
181
+ /***********************************************************************
182
+ * sendInterest
183
+ ***********************************************************************
184
+ *
185
+ **********************************************************************/
186
+ static void sendInterest( tr_peer_t * peer, int yes )
187
+ {
188
+ uint8_t * p;
189
+
190
+ p = getPointerForSize( peer, 5 );
191
+
192
+ TR_HTONL( 1, p );
193
+ p[4] = yes ? 2 : 3;
194
+
195
+ peer->amInterested = yes;
196
+
197
+ peer_dbg( "SEND %sinterested", yes ? "" : "un" );
198
+ }
199
+
200
+ /***********************************************************************
201
+ * sendHave
202
+ ***********************************************************************
203
+ *
204
+ **********************************************************************/
205
+ static void sendHave( tr_peer_t * peer, int piece )
206
+ {
207
+ uint8_t * p;
208
+
209
+ p = getPointerForSize( peer, 9 );
210
+
211
+ TR_HTONL( 5, &p[0] );
212
+ p[4] = 4;
213
+ TR_HTONL( piece, &p[5] );
214
+
215
+ peer_dbg( "SEND have %d", piece );
216
+ }
217
+
218
+ /***********************************************************************
219
+ * sendBitfield
220
+ ***********************************************************************
221
+ * Builds a 'bitfield' message:
222
+ * - size = 5 + X (4 bytes)
223
+ * - id = 5 (1 byte)
224
+ * - bitfield (X bytes)
225
+ **********************************************************************/
226
+ static void sendBitfield( tr_torrent_t * tor, tr_peer_t * peer )
227
+ {
228
+ uint8_t * p;
229
+ int bitfieldSize = ( tor->info.pieceCount + 7 ) / 8;
230
+
231
+ p = getPointerForSize( peer, 5 + bitfieldSize );
232
+
233
+ TR_HTONL( 1 + bitfieldSize, p );
234
+ p[4] = 5;
235
+ memcpy( &p[5], tr_cpPieceBitfield( tor->completion ), bitfieldSize );
236
+
237
+ peer_dbg( "SEND bitfield" );
238
+ }
239
+
240
+ /***********************************************************************
241
+ * sendRequest
242
+ ***********************************************************************
243
+ *
244
+ **********************************************************************/
245
+ static void sendRequest( tr_torrent_t * tor, tr_peer_t * peer, int block )
246
+ {
247
+ tr_info_t * inf = &tor->info;
248
+ tr_request_t * r;
249
+ uint8_t * p;
250
+
251
+ /* Get the piece the block is a part of, its position in the piece
252
+ and its size */
253
+ r = &peer->inRequests[peer->inRequestCount];
254
+ r->index = block / ( inf->pieceSize / tor->blockSize );
255
+ r->begin = ( block % ( inf->pieceSize / tor->blockSize ) ) *
256
+ tor->blockSize;
257
+ r->length = tor->blockSize;
258
+ if( block == tor->blockCount - 1 )
259
+ {
260
+ int lastSize = inf->totalSize % tor->blockSize;
261
+ if( lastSize )
262
+ {
263
+ r->length = lastSize;
264
+ }
265
+ }
266
+ (peer->inRequestCount)++;
267
+
268
+ /* Build the "ask" message */
269
+ p = getPointerForSize( peer, 17 );
270
+
271
+ TR_HTONL( 13, p );
272
+ p[4] = 6;
273
+ TR_HTONL( r->index, p + 5 );
274
+ TR_HTONL( r->begin, p + 9 );
275
+ TR_HTONL( r->length, p + 13 );
276
+
277
+ tr_cpDownloaderAdd( tor->completion, block );
278
+
279
+ peer_dbg( "SEND request %d/%d (%d bytes)",
280
+ r->index, r->begin, r->length );
281
+ }
282
+
283
+ /***********************************************************************
284
+ * sendCancel
285
+ ***********************************************************************
286
+ *
287
+ **********************************************************************/
288
+ static void sendCancel( tr_torrent_t * tor, int block )
289
+ {
290
+ int i, j;
291
+ uint8_t * p;
292
+ tr_peer_t * peer;
293
+ tr_request_t * r;
294
+
295
+ for( i = 0; i < tor->peerCount; i++ )
296
+ {
297
+ peer = tor->peers[i];
298
+
299
+ for( j = 1; j < peer->inRequestCount; j++ )
300
+ {
301
+ r = &peer->inRequests[j];
302
+
303
+ if( block != tr_block( r->index, r->begin ) )
304
+ {
305
+ continue;
306
+ }
307
+
308
+ p = getPointerForSize( peer, 17 );
309
+
310
+ /* Build the "cancel" message */
311
+ TR_HTONL( 13, p );
312
+ p[4] = 8;
313
+ TR_HTONL( r->index, p + 5 );
314
+ TR_HTONL( r->begin, p + 9 );
315
+ TR_HTONL( r->length, p + 13 );
316
+
317
+ peer_dbg( "SEND cancel %d/%d (%d bytes)",
318
+ r->index, r->begin, r->length );
319
+
320
+ (peer->inRequestCount)--;
321
+ memmove( &peer->inRequests[j], &peer->inRequests[j+1],
322
+ ( peer->inRequestCount - j ) * sizeof( tr_request_t ) );
323
+ break;
324
+ }
325
+ }
326
+ }
@@ -0,0 +1,564 @@
1
+ /******************************************************************************
2
+ * $Id: peerparse.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
+ /***********************************************************************
26
+ * This file handles all incoming messages
27
+ **********************************************************************/
28
+
29
+ /***********************************************************************
30
+ * parseChoke
31
+ ***********************************************************************
32
+ *
33
+ **********************************************************************/
34
+ static inline int parseChoke( tr_torrent_t * tor, tr_peer_t * peer,
35
+ int len, int choking )
36
+ {
37
+ tr_request_t * r;
38
+ int i;
39
+
40
+ if( len != 1 )
41
+ {
42
+ peer_dbg( "GET %schoke, invalid", choking ? "" : "un" );
43
+ return 1;
44
+ }
45
+
46
+ peer_dbg( "GET %schoke", choking ? "" : "un" );
47
+
48
+ peer->peerChoking = choking;
49
+
50
+ if( choking )
51
+ {
52
+ /* Discard all pending requests */
53
+ for( i = 0; i < peer->inRequestCount; i++ )
54
+ {
55
+ r = &peer->inRequests[i];
56
+ tr_cpDownloaderRem( tor->completion, tr_block(r->index,r->begin) );
57
+ }
58
+ peer->inRequestCount = 0;
59
+ }
60
+
61
+ return 0;
62
+ }
63
+
64
+ /***********************************************************************
65
+ * parseInterested
66
+ ***********************************************************************
67
+ *
68
+ **********************************************************************/
69
+ static inline int parseInterested( tr_peer_t * peer, int len,
70
+ int interested )
71
+ {
72
+ if( len != 1 )
73
+ {
74
+ peer_dbg( "GET %sinterested, invalid", interested ? "" : "un" );
75
+ return 1;
76
+ }
77
+
78
+ peer_dbg( "GET %sinterested", interested ? "" : "un" );
79
+
80
+ peer->peerInterested = interested;
81
+
82
+ return 0;
83
+ }
84
+
85
+ /***********************************************************************
86
+ * parseHave
87
+ ***********************************************************************
88
+ *
89
+ **********************************************************************/
90
+ static inline int parseHave( tr_torrent_t * tor, tr_peer_t * peer,
91
+ uint8_t * p, int len )
92
+ {
93
+ uint32_t piece;
94
+
95
+ if( len != 5 )
96
+ {
97
+ peer_dbg( "GET have, invalid" );
98
+ return 1;
99
+ }
100
+
101
+ TR_NTOHL( p, piece );
102
+
103
+ peer_dbg( "GET have %d", piece );
104
+
105
+ if( !peer->bitfield )
106
+ {
107
+ peer->bitfield = calloc( ( tor->info.pieceCount + 7 ) / 8, 1 );
108
+ }
109
+ tr_bitfieldAdd( peer->bitfield, piece );
110
+ updateInterest( tor, peer );
111
+
112
+ return 0;
113
+ }
114
+
115
+ static inline int parseBitfield( tr_torrent_t * tor, tr_peer_t * peer,
116
+ uint8_t * p, int len )
117
+ {
118
+ tr_info_t * inf = &tor->info;
119
+ int bitfieldSize;
120
+
121
+ bitfieldSize = ( inf->pieceCount + 7 ) / 8;
122
+
123
+ if( len != 1 + bitfieldSize )
124
+ {
125
+ peer_dbg( "GET bitfield, wrong size" );
126
+ return 1;
127
+ }
128
+
129
+ /* Make sure the spare bits are unset */
130
+ if( ( inf->pieceCount & 0x7 ) )
131
+ {
132
+ uint8_t lastByte;
133
+
134
+ lastByte = p[bitfieldSize-1];
135
+ lastByte <<= inf->pieceCount & 0x7;
136
+ lastByte &= 0xFF;
137
+
138
+ if( lastByte )
139
+ {
140
+ peer_dbg( "GET bitfield, spare bits set" );
141
+ return 1;
142
+ }
143
+ }
144
+
145
+ peer_dbg( "GET bitfield, ok" );
146
+
147
+ if( !peer->bitfield )
148
+ {
149
+ peer->bitfield = malloc( bitfieldSize );
150
+ }
151
+ memcpy( peer->bitfield, p, bitfieldSize );
152
+ updateInterest( tor, peer );
153
+
154
+ return 0;
155
+ }
156
+
157
+ static inline int parseRequest( tr_peer_t * peer, uint8_t * p, int len )
158
+ {
159
+ int index, begin, length;
160
+ tr_request_t * r;
161
+
162
+ if( len != 13 )
163
+ {
164
+ peer_dbg( "GET request, invalid" );
165
+ return 1;
166
+ }
167
+
168
+ if( peer->amChoking )
169
+ {
170
+ /* Didn't he get it? */
171
+ sendChoke( peer, 1 );
172
+ return 0;
173
+ }
174
+
175
+ TR_NTOHL( p, index );
176
+ TR_NTOHL( &p[4], begin );
177
+ TR_NTOHL( &p[8], length );
178
+
179
+ peer_dbg( "GET request %d/%d (%d bytes)",
180
+ index, begin, length );
181
+
182
+ /* TODO sanity checks (do we have the piece, etc) */
183
+
184
+ if( length > 16384 )
185
+ {
186
+ /* Sorry mate */
187
+ return 1;
188
+ }
189
+
190
+ if( peer->outRequestCount >= MAX_REQUEST_COUNT )
191
+ {
192
+ tr_err( "Too many requests" );
193
+ return 1;
194
+ }
195
+
196
+ r = &peer->outRequests[peer->outRequestCount];
197
+ r->index = index;
198
+ r->begin = begin;
199
+ r->length = length;
200
+
201
+ (peer->outRequestCount)++;
202
+
203
+ return 0;
204
+ }
205
+
206
+ static inline int parsePiece( tr_torrent_t * tor, tr_peer_t * peer,
207
+ uint8_t * p, int len )
208
+ {
209
+ int index, begin, block, i, j;
210
+ tr_request_t * r;
211
+
212
+ TR_NTOHL( p, index );
213
+ TR_NTOHL( &p[4], begin );
214
+
215
+ peer_dbg( "GET piece %d/%d (%d bytes)",
216
+ index, begin, len - 9 );
217
+
218
+ if( peer->inRequestCount < 1 )
219
+ {
220
+ /* Our "cancel" was probably late */
221
+ peer_dbg( "not expecting a block" );
222
+ return 0;
223
+ }
224
+
225
+ r = &peer->inRequests[0];
226
+ if( index != r->index || begin != r->begin )
227
+ {
228
+ int suckyClient;
229
+
230
+ /* Either our "cancel" was late, or this is a sucky
231
+ client that cannot deal with multiple requests */
232
+ suckyClient = 0;
233
+ for( i = 0; i < peer->inRequestCount; i++ )
234
+ {
235
+ r = &peer->inRequests[i];
236
+
237
+ if( index != r->index || begin != r->begin )
238
+ {
239
+ continue;
240
+ }
241
+
242
+ /* Sucky client, he dropped the previous requests */
243
+ peer_dbg( "block was expected later" );
244
+ for( j = 0; j < i; j++ )
245
+ {
246
+ r = &peer->inRequests[j];
247
+ tr_cpDownloaderRem( tor->completion,
248
+ tr_block(r->index,r->begin) );
249
+ }
250
+ suckyClient = 1;
251
+ peer->inRequestCount -= i;
252
+ memmove( &peer->inRequests[0], &peer->inRequests[i],
253
+ peer->inRequestCount * sizeof( tr_request_t ) );
254
+ r = &peer->inRequests[0];
255
+ break;
256
+ }
257
+
258
+ if( !suckyClient )
259
+ {
260
+ r = &peer->inRequests[0];
261
+ peer_dbg( "wrong block (expecting %d/%d)",
262
+ r->index, r->begin );
263
+ return 0;
264
+ }
265
+ }
266
+
267
+ if( len - 9 != r->length )
268
+ {
269
+ peer_dbg( "wrong size (expecting %d)", r->length );
270
+ return 1;
271
+ }
272
+
273
+ tor->downloaded += r->length;
274
+
275
+ block = tr_block( r->index, r->begin );
276
+ if( tr_cpBlockIsComplete( tor->completion, block ) )
277
+ {
278
+ peer_dbg( "have this block already" );
279
+ (peer->inRequestCount)--;
280
+ memmove( &peer->inRequests[0], &peer->inRequests[1],
281
+ peer->inRequestCount * sizeof( tr_request_t ) );
282
+ return 0;
283
+ }
284
+
285
+ /* set blame/credit for this piece */
286
+ if( !peer->blamefield )
287
+ {
288
+ peer->blamefield = calloc( ( tor->info.pieceCount + 7 ) / 8, 1 );
289
+ }
290
+ tr_bitfieldAdd( peer->blamefield, index );
291
+
292
+ tr_cpBlockAdd( tor->completion, block );
293
+ tr_ioWrite( tor->io, index, begin, len - 9, &p[8] );
294
+ tr_cpDownloaderRem( tor->completion, block );
295
+
296
+ sendCancel( tor, block );
297
+
298
+ if( tr_cpPieceIsComplete( tor->completion, index ) )
299
+ {
300
+ tr_peer_t * otherPeer;
301
+
302
+ for( i = 0; i < tor->peerCount; i++ )
303
+ {
304
+ otherPeer = tor->peers[i];
305
+
306
+ if( otherPeer->status < PEER_STATUS_CONNECTED )
307
+ {
308
+ continue;
309
+ }
310
+
311
+ sendHave( otherPeer, index );
312
+ updateInterest( tor, otherPeer );
313
+ }
314
+ }
315
+
316
+ (peer->inRequestCount)--;
317
+ memmove( &peer->inRequests[0], &peer->inRequests[1],
318
+ peer->inRequestCount * sizeof( tr_request_t ) );
319
+
320
+ return 0;
321
+ }
322
+
323
+ static inline int parseCancel( tr_peer_t * peer, uint8_t * p, int len )
324
+ {
325
+ int index, begin, length;
326
+ int i;
327
+ tr_request_t * r;
328
+
329
+ if( len != 13 )
330
+ {
331
+ peer_dbg( "GET cancel, invalid" );
332
+ return 1;
333
+ }
334
+
335
+ TR_NTOHL( p, index );
336
+ TR_NTOHL( &p[4], begin );
337
+ TR_NTOHL( &p[8], length );
338
+
339
+ peer_dbg( "GET cancel %d/%d (%d bytes)",
340
+ index, begin, length );
341
+
342
+ for( i = 0; i < peer->outRequestCount; i++ )
343
+ {
344
+ r = &peer->outRequests[i];
345
+ if( r->index == index && r->begin == begin &&
346
+ r->length == length )
347
+ {
348
+ (peer->outRequestCount)--;
349
+ memmove( &r[0], &r[1], sizeof( tr_request_t ) *
350
+ ( peer->outRequestCount - i ) );
351
+ break;
352
+ }
353
+ }
354
+
355
+ return 0;
356
+ }
357
+
358
+ static inline int parsePort( tr_peer_t * peer, uint8_t * p, int len )
359
+ {
360
+ in_port_t port;
361
+
362
+ if( len != 3 )
363
+ {
364
+ peer_dbg( "GET port, invalid" );
365
+ return 1;
366
+ }
367
+
368
+ port = *( (in_port_t *) p );
369
+ peer_dbg( "GET port %d", ntohs( port ) );
370
+
371
+ return 0;
372
+ }
373
+
374
+ static inline int parseMessage( tr_torrent_t * tor, tr_peer_t * peer,
375
+ uint8_t * p, int len )
376
+ {
377
+ char id;
378
+
379
+ /* Type of the message */
380
+ id = *(p++);
381
+
382
+ switch( id )
383
+ {
384
+ case 0:
385
+ return parseChoke( tor, peer, len, 1 );
386
+ case 1:
387
+ return parseChoke( tor, peer, len, 0 );
388
+ case 2:
389
+ return parseInterested( peer, len, 1 );
390
+ case 3:
391
+ return parseInterested( peer, len, 0 );
392
+ case 4:
393
+ return parseHave( tor, peer, p, len );
394
+ case 5:
395
+ return parseBitfield( tor, peer, p, len );
396
+ case 6:
397
+ return parseRequest( peer, p, len );
398
+ case 7:
399
+ return parsePiece( tor, peer, p, len );
400
+ case 8:
401
+ return parseCancel( peer, p, len );
402
+ case 9:
403
+ return parsePort( peer, p, len );
404
+ }
405
+
406
+ peer_dbg( "Unknown message '%d'", id );
407
+ return 1;
408
+ }
409
+
410
+ static inline int parseBufHeader( tr_peer_t * peer )
411
+ {
412
+ uint8_t * p = peer->buf;
413
+
414
+ if( 4 > peer->pos )
415
+ {
416
+ return 0;
417
+ }
418
+
419
+ if( p[0] != 19 || memcmp( &p[1], "Bit", 3 ) )
420
+ {
421
+ /* Don't wait until we get 68 bytes, this is wrong
422
+ already */
423
+ peer_dbg( "GET handshake, invalid" );
424
+ tr_netSend( peer->socket, (uint8_t *) "Nice try...\r\n", 13 );
425
+ return 1;
426
+ }
427
+ if( peer->pos < 68 )
428
+ {
429
+ return 0;
430
+ }
431
+ if( memcmp( &p[4], "Torrent protocol", 16 ) )
432
+ {
433
+ peer_dbg( "GET handshake, invalid" );
434
+ return 1;
435
+ }
436
+
437
+ return 0;
438
+ }
439
+
440
+ static uint8_t * parseBufHash( tr_peer_t * peer )
441
+ {
442
+ if( 48 > peer->pos )
443
+ {
444
+ return NULL;
445
+ }
446
+ else
447
+ {
448
+ return peer->buf + 28;
449
+ }
450
+ }
451
+
452
+ static inline int parseBuf( tr_torrent_t * tor, tr_peer_t * peer )
453
+ {
454
+ tr_info_t * inf = &tor->info;
455
+
456
+ int i;
457
+ int len;
458
+ uint8_t * p = peer->buf;
459
+ uint8_t * end = &p[peer->pos];
460
+
461
+ if( peer->banned )
462
+ {
463
+ /* Don't even parse, we only stay connected */
464
+ peer->pos = 0;
465
+ return 0;
466
+ }
467
+
468
+ while( peer->pos >= 4 )
469
+ {
470
+ if( peer->status & PEER_STATUS_HANDSHAKE )
471
+ {
472
+ char * client;
473
+
474
+ if( parseBufHeader( peer ) )
475
+ {
476
+ return 1;
477
+ }
478
+
479
+ if( peer->pos < 68 )
480
+ {
481
+ break;
482
+ }
483
+
484
+ if( memcmp( &p[28], inf->hash, 20 ) )
485
+ {
486
+ peer_dbg( "GET handshake, wrong torrent hash" );
487
+ return 1;
488
+ }
489
+
490
+ if( !memcmp( &p[48], tor->id, 20 ) )
491
+ {
492
+ /* We are connected to ourselves... */
493
+ peer_dbg( "GET handshake, that is us" );
494
+ return 1;
495
+ }
496
+
497
+ peer->status = PEER_STATUS_CONNECTED;
498
+ memcpy( peer->id, &p[48], 20 );
499
+ p += 68;
500
+ peer->pos -= 68;
501
+
502
+ for( i = 0; i < tor->peerCount; i++ )
503
+ {
504
+ if( tor->peers[i] == peer )
505
+ {
506
+ continue;
507
+ }
508
+ if( !peerCmp( peer, tor->peers[i] ) )
509
+ {
510
+ peer_dbg( "GET handshake, duplicate" );
511
+ return 1;
512
+ }
513
+ }
514
+
515
+ client = tr_clientForId( (uint8_t *) peer->id );
516
+ peer_dbg( "GET handshake, ok (%s)", client );
517
+ free( client );
518
+
519
+ sendBitfield( tor, peer );
520
+
521
+ continue;
522
+ }
523
+
524
+ /* Get payload size */
525
+ TR_NTOHL( p, len );
526
+ p += 4;
527
+
528
+ if( len > 9 + tor->blockSize )
529
+ {
530
+ /* This should never happen. Drop that peer */
531
+ peer_dbg( "message too large (%d bytes)", len );
532
+ return 1;
533
+ }
534
+
535
+ if( !len )
536
+ {
537
+ /* keep-alive */
538
+ peer_dbg( "GET keep-alive" );
539
+ peer->pos -= 4;
540
+ continue;
541
+ }
542
+
543
+ if( &p[len] > end )
544
+ {
545
+ /* We do not have the entire message */
546
+ p -= 4;
547
+ break;
548
+ }
549
+
550
+ /* Remaining data after this message */
551
+ peer->pos -= 4 + len;
552
+
553
+ if( parseMessage( tor, peer, p, len ) )
554
+ {
555
+ return 1;
556
+ }
557
+
558
+ p += len;
559
+ }
560
+
561
+ memmove( peer->buf, p, peer->pos );
562
+
563
+ return 0;
564
+ }