Lines 2-13
Link Here
|
2 |
|
2 |
|
3 |
#include <stdlib.h> |
3 |
#include <stdlib.h> |
4 |
#include <string.h> |
4 |
#include <string.h> |
|
|
5 |
#include <ctype.h> |
5 |
|
6 |
|
|
|
7 |
#include "btstream.h" |
6 |
#include "./btcontent.h" |
8 |
#include "./btcontent.h" |
7 |
#include "./msgencode.h" |
9 |
#include "./msgencode.h" |
8 |
#include "./peerlist.h" |
10 |
#include "./peerlist.h" |
9 |
#include "./btconfig.h" |
11 |
#include "./btconfig.h" |
10 |
|
12 |
|
|
|
13 |
size_t get_nl(char *sfrom) |
14 |
{ |
15 |
unsigned char *from = (unsigned char *)sfrom; |
16 |
size_t t; |
17 |
t = (*from++) << 24; |
18 |
t |= (*from++) << 16; |
19 |
t |= (*from++) << 8; |
20 |
t |= *from; |
21 |
return t; |
22 |
} |
23 |
|
24 |
void set_nl(char *sto, size_t from) |
25 |
{ |
26 |
unsigned char *to = (unsigned char *)sto; |
27 |
*to++ = (from >> 24) & 0xff; |
28 |
*to++ = (from >> 16) & 0xff; |
29 |
*to++ = (from >> 8) & 0xff; |
30 |
*to = from & 0xff; |
31 |
} |
32 |
|
11 |
btBasic Self; |
33 |
btBasic Self; |
12 |
|
34 |
|
13 |
void btBasic::SetIp(struct sockaddr_in addr) |
35 |
void btBasic::SetIp(struct sockaddr_in addr) |
Lines 44-54
Link Here
|
44 |
|
66 |
|
45 |
int btPeer::Need_Remote_Data() |
67 |
int btPeer::Need_Remote_Data() |
46 |
{ |
68 |
{ |
|
|
69 |
|
47 |
if( BTCONTENT.pBF->IsFull()) return 0; |
70 |
if( BTCONTENT.pBF->IsFull()) return 0; |
48 |
else if( bitfield.IsFull() ) return 1; |
71 |
else if( bitfield.IsFull() ) return 1; |
49 |
else{ |
72 |
else{ |
50 |
BitField tmpBitfield = bitfield; |
73 |
BitField tmpBitfield = bitfield; |
51 |
tmpBitfield.Except(*BTCONTENT.pBF); |
74 |
tmpBitfield.Except(*BTCONTENT.pBF); |
|
|
75 |
tmpBitfield.Except(*BTCONTENT.pBFilter); |
52 |
return tmpBitfield.IsEmpty() ? 0 : 1; |
76 |
return tmpBitfield.IsEmpty() ? 0 : 1; |
53 |
} |
77 |
} |
54 |
return 0; |
78 |
return 0; |
Lines 65-70
Link Here
|
65 |
|
89 |
|
66 |
m_err_count = 0; |
90 |
m_err_count = 0; |
67 |
m_cached_idx = BTCONTENT.GetNPieces(); |
91 |
m_cached_idx = BTCONTENT.GetNPieces(); |
|
|
92 |
m_standby = 0; |
68 |
} |
93 |
} |
69 |
|
94 |
|
70 |
int btPeer::SetLocal(unsigned char s) |
95 |
int btPeer::SetLocal(unsigned char s) |
Lines 72-91
Link Here
|
72 |
switch(s){ |
97 |
switch(s){ |
73 |
case M_CHOKE: |
98 |
case M_CHOKE: |
74 |
if( m_state.local_choked ) return 0; |
99 |
if( m_state.local_choked ) return 0; |
|
|
100 |
time(&m_unchoke_timestamp); |
101 |
// if(arg_verbose) fprintf(stderr, "Choking %p\n", this); |
102 |
if(arg_verbose) fprintf(stderr, "Choking %p (D=%lluMB@%uK/s)\n", this, |
103 |
TotalDL() >> 20, RateDL() >> 10); |
75 |
m_state.local_choked = 1; |
104 |
m_state.local_choked = 1; |
76 |
break; |
105 |
break; |
77 |
case M_UNCHOKE: |
106 |
case M_UNCHOKE: |
78 |
if( !reponse_q.IsEmpty() ) StartULTimer(); |
107 |
if( !reponse_q.IsEmpty() ) StartULTimer(); |
79 |
if( !m_state.local_choked ) return 0; |
108 |
if( !m_state.local_choked ) return 0; |
80 |
time(&m_unchoke_timestamp); |
109 |
time(&m_unchoke_timestamp); |
|
|
110 |
// if(arg_verbose) fprintf(stderr, "Unchoking %p\n", this); |
111 |
if(arg_verbose) fprintf(stderr, "Unchoking %p (D=%lluMB@%uK/s)\n", this, |
112 |
TotalDL() >> 20, RateDL() >> 10); |
81 |
m_state.local_choked = 0; |
113 |
m_state.local_choked = 0; |
82 |
break; |
114 |
break; |
83 |
case M_INTERESTED: |
115 |
case M_INTERESTED: |
|
|
116 |
m_standby = 0; |
84 |
if( m_state.local_interested ) return 0; |
117 |
if( m_state.local_interested ) return 0; |
|
|
118 |
if(arg_verbose) fprintf(stderr, "Interested in %p\n", this); |
85 |
m_state.local_interested = 1; |
119 |
m_state.local_interested = 1; |
86 |
break; |
120 |
break; |
87 |
case M_NOT_INTERESTED: |
121 |
case M_NOT_INTERESTED: |
88 |
if( !m_state.local_interested ) return 0; |
122 |
if( !m_state.local_interested ) return 0; |
|
|
123 |
if(arg_verbose) fprintf(stderr, "Not interested in %p\n", this); |
89 |
m_state.local_interested = 0; |
124 |
m_state.local_interested = 0; |
90 |
break; |
125 |
break; |
91 |
default: |
126 |
default: |
Lines 97-108
Link Here
|
97 |
int btPeer::RequestPiece() |
132 |
int btPeer::RequestPiece() |
98 |
{ |
133 |
{ |
99 |
size_t idx; |
134 |
size_t idx; |
|
|
135 |
int endgame = 0; |
100 |
|
136 |
|
101 |
PENDINGQUEUE.ReAssign(&request_q,bitfield); |
137 |
PENDINGQUEUE.ReAssign(&request_q,bitfield); |
102 |
|
138 |
|
103 |
if( !request_q.IsEmpty() ) return SendRequest(); |
139 |
if( !request_q.IsEmpty() ) return SendRequest(); |
104 |
|
140 |
|
105 |
if( m_cached_idx < BTCONTENT.GetNPieces() ){ |
141 |
if( m_cached_idx < BTCONTENT.GetNPieces() && !BTCONTENT.pBF->IsEmpty() ){ |
|
|
142 |
// A HAVE msg already selected what we want from this peer |
143 |
// but ignore it in initial-piece mode. |
106 |
idx = m_cached_idx; |
144 |
idx = m_cached_idx; |
107 |
m_cached_idx = BTCONTENT.GetNPieces(); |
145 |
m_cached_idx = BTCONTENT.GetNPieces(); |
108 |
if( !BTCONTENT.pBF->IsSet(idx) && |
146 |
if( !BTCONTENT.pBF->IsSet(idx) && |
Lines 110-148
Link Here
|
110 |
!WORLD.AlreadyRequested(idx) ){ |
148 |
!WORLD.AlreadyRequested(idx) ){ |
111 |
return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest(); |
149 |
return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest(); |
112 |
} |
150 |
} |
113 |
}else{ |
151 |
} // If we didn't want the cached piece, select another. |
|
|
152 |
if( BTCONTENT.pBF->IsEmpty() ){ |
153 |
// If we don't have a complete piece yet, try to get one that's already |
154 |
// in progress. (Initial-piece mode) |
155 |
btPeer *peer = WORLD.Who_Can_Duplicate(this, BTCONTENT.GetNPieces()); |
156 |
if(peer){ |
157 |
if(arg_verbose) fprintf( stderr, "Duping: %p to %p (#%u)\n", |
158 |
peer, this, peer->request_q.GetRequestIdx() ); |
159 |
return (request_q.CopyShuffle(peer->request_q) < 0) ? -1 : SendRequest(); |
160 |
} |
161 |
} // Doesn't have a piece that's already in progress--choose another. |
114 |
BitField tmpBitField; |
162 |
BitField tmpBitField; |
115 |
if( bitfield.IsFull() ){ |
163 |
if( bitfield.IsFull() ){ |
|
|
164 |
// peer is a seed |
116 |
tmpBitField = *BTCONTENT.pBF; |
165 |
tmpBitField = *BTCONTENT.pBF; |
117 |
tmpBitField.Invert(); |
166 |
tmpBitField.Invert(); |
118 |
}else{ |
167 |
}else{ |
119 |
tmpBitField = bitfield; |
168 |
tmpBitField = bitfield; |
120 |
tmpBitField.Except(*BTCONTENT.pBF); |
169 |
tmpBitField.Except(*BTCONTENT.pBF); |
121 |
} |
170 |
} |
|
|
171 |
// The filter tells what we don't want. |
172 |
tmpBitField.Except(*BTCONTENT.pBFilter); |
173 |
// tmpBitField tells what we need from this peer... |
122 |
|
174 |
|
123 |
if( !tmpBitField.IsEmpty() ){ |
175 |
if( !tmpBitField.IsEmpty() ){ |
124 |
WORLD.CheckBitField(tmpBitField); |
176 |
BitField tmpBitField2 = tmpBitField; |
125 |
if(tmpBitField.IsEmpty()){ |
177 |
WORLD.CheckBitField(tmpBitField2); |
126 |
|
178 |
// [tmpBitField2]... that we haven't requested from anyone. |
127 |
btPeer *peer = WORLD.Who_Can_Abandon(this); |
179 |
if(tmpBitField2.IsEmpty()){ |
128 |
if(peer){ |
180 |
// Everything this peer has that I want, I've already requested. |
129 |
peer->StopDLTimer(); |
181 |
endgame = ( WORLD.Pieces_I_Can_Get() - BTCONTENT.pBF->Count() ) |
130 |
request_q = peer->request_q; |
182 |
< WORLD.TotalPeers(); |
131 |
|
183 |
if(endgame){ // OK to duplicate a request. |
132 |
if(peer->CancelRequest(request_q.GetHead()) < 0 || |
184 |
// idx = tmpBitField.Random(); |
133 |
peer->RequestCheck() < 0){ |
185 |
idx = 0; // flag for Who_Can_Duplicate() |
134 |
peer->CloseConnection(); |
186 |
btPeer *peer = WORLD.Who_Can_Duplicate(this, idx); |
135 |
} |
187 |
if(arg_verbose) fprintf( stderr, "Duping: %p to %p (#%u)\n", |
136 |
|
188 |
peer, this, peer->request_q.GetRequestIdx() ); |
137 |
return SendRequest(); |
189 |
return (request_q.CopyShuffle(peer->request_q) < 0) ? |
138 |
} |
190 |
-1 : SendRequest(); |
139 |
|
191 |
}else{ // not endgame mode |
|
|
192 |
btPeer *peer = WORLD.Who_Can_Abandon(this); // slowest choice |
193 |
if(peer){ |
194 |
// Cancel a request to the slowest peer & request it from this one. |
195 |
if(arg_verbose) fprintf( stderr, "Reassigning %p to %p (#%u)\n", |
196 |
peer, this, peer->request_q.GetRequestIdx() ); |
197 |
peer->StopDLTimer(); |
198 |
// RequestQueue class "moves" rather than "copies" in assignment! |
199 |
request_q = peer->request_q; |
200 |
|
201 |
if(peer->CancelRequest(request_q.GetHead()) < 0 || |
202 |
peer->RequestCheck() < 0){ |
203 |
peer->CloseConnection(); |
204 |
} |
205 |
return SendRequest(); |
206 |
}else m_standby = 1; // nothing to do at the moment |
207 |
} |
140 |
}else{ |
208 |
}else{ |
141 |
idx = tmpBitField.Random(); |
209 |
// Request something that we haven't requested yet (most common case). |
142 |
return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest(); |
210 |
idx = tmpBitField2.Random(); |
|
|
211 |
return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest(); |
143 |
} |
212 |
} |
|
|
213 |
} else { |
214 |
// We don't need anything from the peer. How'd we get here? |
215 |
return SetLocal(M_NOT_INTERESTED); |
144 |
} |
216 |
} |
145 |
} |
|
|
146 |
return 0; |
217 |
return 0; |
147 |
} |
218 |
} |
148 |
|
219 |
|
Lines 152-188
Link Here
|
152 |
|
223 |
|
153 |
char *msgbuf = stream.in_buffer.BasePointer(); |
224 |
char *msgbuf = stream.in_buffer.BasePointer(); |
154 |
|
225 |
|
155 |
r = ntohl(*(size_t*) msgbuf); |
226 |
r = get_nl(msgbuf); |
156 |
|
227 |
|
|
|
228 |
// Don't require keepalives if we're receiving other messages. |
229 |
time(&m_last_timestamp); |
157 |
if( 0 == r ){ |
230 |
if( 0 == r ){ |
158 |
time(&m_last_timestamp); |
|
|
159 |
if( !m_f_keepalive ) if( stream.Send_Keepalive() < 0 ) return -1; |
231 |
if( !m_f_keepalive ) if( stream.Send_Keepalive() < 0 ) return -1; |
160 |
m_f_keepalive = 0; |
232 |
m_f_keepalive = 0; |
161 |
return (!m_state.remote_choked && request_q.IsEmpty()) ? RequestCheck() : 0; |
233 |
return 0; |
162 |
}else{ |
234 |
}else{ |
163 |
switch(msgbuf[4]){ |
235 |
switch(msgbuf[4]){ |
164 |
case M_CHOKE: |
236 |
case M_CHOKE: |
165 |
if(H_BASE_LEN != r){ return -1;} |
237 |
if(H_BASE_LEN != r){ return -1;} |
|
|
238 |
if(arg_verbose) fprintf(stderr, "%p choked me\n", this); |
166 |
m_state.remote_choked = 1; |
239 |
m_state.remote_choked = 1; |
167 |
StopDLTimer(); |
240 |
StopDLTimer(); |
168 |
if( !request_q.IsEmpty()){ |
241 |
if( !request_q.IsEmpty()){ |
169 |
PSLICE ps = request_q.GetHead(); |
242 |
PSLICE ps = request_q.GetHead(); |
170 |
PENDINGQUEUE.Pending(&request_q); |
243 |
if( !PENDINGQUEUE.Exist(request_q.GetRequestIdx()) ) |
|
|
244 |
PENDINGQUEUE.Pending(&request_q); |
171 |
if( CancelRequest(ps) < 0) return -1; |
245 |
if( CancelRequest(ps) < 0) return -1; |
172 |
} |
246 |
} |
173 |
return 0; |
247 |
return 0; |
|
|
248 |
|
174 |
case M_UNCHOKE: |
249 |
case M_UNCHOKE: |
175 |
if(H_BASE_LEN != r){return -1;} |
250 |
if(H_BASE_LEN != r){return -1;} |
|
|
251 |
if(arg_verbose) fprintf(stderr, "%p unchoked me\n", this); |
176 |
m_state.remote_choked = 0; |
252 |
m_state.remote_choked = 0; |
|
|
253 |
if(!request_q.IsEmpty()) // shouldn't happen; maybe peer is confused. |
254 |
return SendRequest(); |
177 |
return RequestCheck(); |
255 |
return RequestCheck(); |
178 |
|
256 |
|
179 |
case M_INTERESTED: |
257 |
case M_INTERESTED: |
180 |
if(H_BASE_LEN != r){return -1;} |
258 |
if(H_BASE_LEN != r){return -1;} |
|
|
259 |
if(arg_verbose) fprintf(stderr, "%p is interested\n", this); |
181 |
m_state.remote_interested = 1; |
260 |
m_state.remote_interested = 1; |
182 |
break; |
261 |
break; |
183 |
|
262 |
|
184 |
case M_NOT_INTERESTED: |
263 |
case M_NOT_INTERESTED: |
185 |
if(r != H_BASE_LEN){return -1;} |
264 |
if(r != H_BASE_LEN){return -1;} |
|
|
265 |
if(arg_verbose) fprintf(stderr, "%p is not interested\n", this); |
186 |
|
266 |
|
187 |
m_state.remote_interested = 0; |
267 |
m_state.remote_interested = 0; |
188 |
StopULTimer(); |
268 |
StopULTimer(); |
Lines 190-199
Link Here
|
190 |
/* remove peer's reponse queue */ |
270 |
/* remove peer's reponse queue */ |
191 |
if( !reponse_q.IsEmpty()) reponse_q.Empty(); |
271 |
if( !reponse_q.IsEmpty()) reponse_q.Empty(); |
192 |
return 0; |
272 |
return 0; |
|
|
273 |
|
193 |
case M_HAVE: |
274 |
case M_HAVE: |
194 |
if(H_HAVE_LEN != r){return -1;} |
275 |
if(H_HAVE_LEN != r){return -1;} |
195 |
|
276 |
|
196 |
idx = ntohl(*(size_t*) (msgbuf + 5)); |
277 |
idx = get_nl(msgbuf + 5); |
197 |
|
278 |
|
198 |
if( idx >= BTCONTENT.GetNPieces() || bitfield.IsSet(idx)) return -1; |
279 |
if( idx >= BTCONTENT.GetNPieces() || bitfield.IsSet(idx)) return -1; |
199 |
|
280 |
|
Lines 201-219
Link Here
|
201 |
|
282 |
|
202 |
if( bitfield.IsFull() && BTCONTENT.pBF->IsFull() ){ return -2; } |
283 |
if( bitfield.IsFull() && BTCONTENT.pBF->IsFull() ){ return -2; } |
203 |
|
284 |
|
204 |
if( !BTCONTENT.pBF->IsSet(idx) ) m_cached_idx = idx; |
285 |
if( !BTCONTENT.pBF->IsSet(idx) && !BTCONTENT.pBFilter->IsSet(idx) ){ |
|
|
286 |
m_cached_idx = idx; |
287 |
m_standby = 0; |
288 |
} |
289 |
// if( !BTCONTENT.pBF->IsSet(idx) ) m_cached_idx = idx; |
205 |
|
290 |
|
206 |
return ( !m_state.remote_choked && request_q.IsEmpty() ) ? RequestCheck() : 0; |
291 |
// see if we're Interested now |
|
|
292 |
return request_q.IsEmpty() ? RequestCheck() : 0; |
207 |
|
293 |
|
208 |
case M_REQUEST: |
294 |
case M_REQUEST: |
209 |
if(H_REQUEST_LEN != r || !m_state.remote_interested){ return -1; } |
295 |
if(H_REQUEST_LEN != r || !m_state.remote_interested){ return -1; } |
210 |
|
296 |
|
211 |
idx = ntohl(*(size_t*)(msgbuf + 5)); |
297 |
idx = get_nl(msgbuf + 5); |
212 |
|
298 |
|
213 |
if( !BTCONTENT.pBF->IsSet(idx) ) return -1; |
299 |
if( !BTCONTENT.pBF->IsSet(idx) ) return -1; |
214 |
|
300 |
|
215 |
off = ntohl(*(size_t*)(msgbuf + 9)); |
301 |
off = get_nl(msgbuf + 9); |
216 |
len = ntohl(*(size_t*)(msgbuf + 13)); |
302 |
len = get_nl(msgbuf + 13); |
217 |
|
303 |
|
218 |
if( !reponse_q.IsValidRequest(idx, off, len) ) return -1; |
304 |
if( !reponse_q.IsValidRequest(idx, off, len) ) return -1; |
219 |
|
305 |
|
Lines 222-227
Link Here
|
222 |
case M_PIECE: |
308 |
case M_PIECE: |
223 |
if( request_q.IsEmpty() || !m_state.local_interested){ |
309 |
if( request_q.IsEmpty() || !m_state.local_interested){ |
224 |
m_err_count++; |
310 |
m_err_count++; |
|
|
311 |
if(arg_verbose) fprintf(stderr,"err: %p (%d) Unwanted piece\n", |
312 |
this, m_err_count); |
225 |
return 0; |
313 |
return 0; |
226 |
} |
314 |
} |
227 |
return PieceDeliver(r); |
315 |
return PieceDeliver(r); |
Lines 230-251
Link Here
|
230 |
if( (r - 1) != bitfield.NBytes() || !bitfield.IsEmpty()) return -1; |
318 |
if( (r - 1) != bitfield.NBytes() || !bitfield.IsEmpty()) return -1; |
231 |
bitfield.SetReferBuffer(msgbuf + 5); |
319 |
bitfield.SetReferBuffer(msgbuf + 5); |
232 |
if(bitfield.IsFull() && BTCONTENT.pBF->IsFull()) return -2; |
320 |
if(bitfield.IsFull() && BTCONTENT.pBF->IsFull()) return -2; |
233 |
return 0; |
321 |
|
|
|
322 |
//This is needed in order to set our Interested state |
323 |
return RequestCheck(); // fixed client stall |
234 |
|
324 |
|
235 |
case M_CANCEL: |
325 |
case M_CANCEL: |
236 |
if(r != H_CANCEL_LEN || !m_state.remote_interested) return -1; |
326 |
if(r != H_CANCEL_LEN || !m_state.remote_interested) return -1; |
237 |
|
327 |
|
238 |
idx = ntohl(*(size_t*)(msgbuf + 5)); |
328 |
idx = get_nl(msgbuf + 5); |
239 |
off = ntohl(*(size_t*)(msgbuf + 9)); |
329 |
off = get_nl(msgbuf + 9); |
240 |
len = ntohl(*(size_t*)(msgbuf + 13)); |
330 |
len = get_nl(msgbuf + 13); |
241 |
if( reponse_q.Remove(idx,off,len) < 0 ){ |
331 |
if( reponse_q.Remove(idx,off,len) < 0 ){ |
242 |
m_err_count++; |
332 |
m_err_count++; |
|
|
333 |
if(arg_verbose) fprintf(stderr, "err: %p (%d) Bad cancel\n", |
334 |
this, m_err_count); |
243 |
return 0; |
335 |
return 0; |
244 |
} |
336 |
} |
245 |
if( reponse_q.IsEmpty() ) StopULTimer(); |
337 |
if( reponse_q.IsEmpty() ) StopULTimer(); |
246 |
return 0; |
338 |
return 0; |
247 |
default: |
339 |
default: |
248 |
return -1; // unknow message type |
340 |
if(arg_verbose) fprintf(stderr, "Unknown message type %u from peer %p\n", |
|
|
341 |
msgbuf[4], this); |
342 |
return 0; // ignore unknown message & continue (forward compatibility) |
249 |
} |
343 |
} |
250 |
} |
344 |
} |
251 |
return 0; |
345 |
return 0; |
Lines 279-286
Link Here
|
279 |
int btPeer::SendRequest() |
373 |
int btPeer::SendRequest() |
280 |
{ |
374 |
{ |
281 |
PSLICE ps = request_q.GetHead(); |
375 |
PSLICE ps = request_q.GetHead(); |
282 |
for( ; ps ; ps = ps->next ) |
376 |
if(arg_verbose) fprintf(stderr, "Requesting #%u from %p:", |
|
|
377 |
request_q.GetRequestIdx(), this); |
378 |
for( ; ps ; ps = ps->next ){ |
379 |
if(arg_verbose) fprintf(stderr, "."); |
283 |
if(stream.Send_Request(ps->index,ps->offset,ps->length) < 0){ return -1; } |
380 |
if(stream.Send_Request(ps->index,ps->offset,ps->length) < 0){ return -1; } |
|
|
381 |
} |
382 |
if(arg_verbose) fprintf(stderr, "\n"); |
284 |
|
383 |
|
285 |
return stream.Flush(); |
384 |
return stream.Flush(); |
286 |
} |
385 |
} |
Lines 294-309
Link Here
|
294 |
return stream.Flush(); |
393 |
return stream.Flush(); |
295 |
} |
394 |
} |
296 |
|
395 |
|
|
|
396 |
int btPeer::CancelSliceRequest(size_t idx, size_t off, size_t len) |
397 |
{ |
398 |
PSLICE ps; |
399 |
|
400 |
for(ps = request_q.GetHead() ; ps; ps = ps->next){ |
401 |
if( idx == ps->index && off == ps->offset && len == ps->length ){ |
402 |
if( request_q.Remove(idx,off,len) < 0 ){ |
403 |
m_err_count++; |
404 |
if(arg_verbose) fprintf(stderr,"err: %p (%d) Bad CS remove\n", |
405 |
this, m_err_count); |
406 |
} |
407 |
if(stream.Send_Cancel(idx,off,len) < 0) |
408 |
return -1; |
409 |
return stream.Flush(); |
410 |
} |
411 |
} |
412 |
return 0; |
413 |
} |
414 |
|
297 |
int btPeer::ReportComplete(size_t idx) |
415 |
int btPeer::ReportComplete(size_t idx) |
298 |
{ |
416 |
{ |
299 |
if( BTCONTENT.APieceComplete(idx) ){ |
417 |
if( BTCONTENT.APieceComplete(idx) ){ |
|
|
418 |
if(arg_verbose) fprintf(stderr, "Piece #%u completed\n", idx); |
300 |
WORLD.Tell_World_I_Have(idx); |
419 |
WORLD.Tell_World_I_Have(idx); |
|
|
420 |
PENDINGQUEUE.Delete(idx); |
301 |
if( BTCONTENT.pBF->IsFull() ){ |
421 |
if( BTCONTENT.pBF->IsFull() ){ |
302 |
ResetDLTimer(); |
422 |
ResetDLTimer(); |
303 |
WORLD.CloseAllConnectionToSeed(); |
423 |
WORLD.CloseAllConnectionToSeed(); |
304 |
} |
424 |
} |
305 |
}else |
425 |
|
|
|
426 |
if( arg_file_to_download ){ |
427 |
BitField tmpBitField = *BTCONTENT.pBF; |
428 |
tmpBitField.Except(*BTCONTENT.pBFilter); |
429 |
|
430 |
while( arg_file_to_download && |
431 |
tmpBitField.Count() >= BTCONTENT.getFilePieces(arg_file_to_download) ){ |
432 |
//when the file is complete, we go after the next |
433 |
++arg_file_to_download; |
434 |
BTCONTENT.FlushCache(); |
435 |
BTCONTENT.SetFilter(); |
436 |
tmpBitField = *BTCONTENT.pBF; |
437 |
tmpBitField.Except(*BTCONTENT.pBFilter); |
438 |
} |
439 |
WORLD.CheckInterest(); |
440 |
} |
441 |
}else{ |
306 |
m_err_count++; |
442 |
m_err_count++; |
|
|
443 |
if(arg_verbose) fprintf(stderr, "err: %p (%d) Bad complete\n", |
444 |
this, m_err_count); |
445 |
} |
307 |
return (P_FAILED == m_status) ? -1 : RequestCheck(); |
446 |
return (P_FAILED == m_status) ? -1 : RequestCheck(); |
308 |
} |
447 |
} |
309 |
|
448 |
|
Lines 312-323
Link Here
|
312 |
size_t idx,off,len; |
451 |
size_t idx,off,len; |
313 |
char *msgbuf = stream.in_buffer.BasePointer(); |
452 |
char *msgbuf = stream.in_buffer.BasePointer(); |
314 |
|
453 |
|
315 |
idx = ntohl(*(size_t*) (msgbuf + 5)); |
454 |
idx = get_nl(msgbuf + 5); |
316 |
off = ntohl(*(size_t*) (msgbuf + 9)); |
455 |
off = get_nl(msgbuf + 9); |
317 |
len = mlen - 9; |
456 |
len = mlen - 9; |
318 |
|
457 |
|
319 |
if( request_q.Remove(idx,off,len) < 0 ){ |
458 |
if( request_q.Remove(idx,off,len) < 0 ){ |
320 |
m_err_count++; |
459 |
m_err_count++; |
|
|
460 |
if(arg_verbose) fprintf(stderr, "err: %p (%d) Bad remove\n", |
461 |
this, m_err_count); |
321 |
return 0; |
462 |
return 0; |
322 |
} |
463 |
} |
323 |
|
464 |
|
Lines 329-341
Link Here
|
329 |
Self.DataRecved(len); |
470 |
Self.DataRecved(len); |
330 |
DataRecved(len); |
471 |
DataRecved(len); |
331 |
|
472 |
|
|
|
473 |
// Check for & cancel requests for this slice from other peers in initial |
474 |
// and endgame modes. |
475 |
if( BTCONTENT.pBF->Count() < 2 || |
476 |
WORLD.Pieces_I_Can_Get() - BTCONTENT.pBF->Count() < WORLD.TotalPeers() ){ |
477 |
WORLD.CancelSlice(idx, off, len); |
478 |
PENDINGQUEUE.DeleteSlice(idx, off, len); |
479 |
} |
480 |
|
332 |
/* if piece download complete. */ |
481 |
/* if piece download complete. */ |
333 |
return request_q.IsEmpty() ? ReportComplete(idx) : 0; |
482 |
return request_q.IsEmpty() ? ReportComplete(idx) : 0; |
334 |
} |
483 |
} |
335 |
|
484 |
|
336 |
int btPeer::RequestCheck() |
485 |
int btPeer::RequestCheck() |
337 |
{ |
486 |
{ |
338 |
if( BandWidthLimit() ) return 0; |
487 |
if( BandWidthLimitDown() ) return 0; |
339 |
|
488 |
|
340 |
if( BTCONTENT.pBF->IsFull() ){ |
489 |
if( BTCONTENT.pBF->IsFull() ){ |
341 |
if( bitfield.IsFull() ){ return -1; } |
490 |
if( bitfield.IsFull() ){ return -1; } |
Lines 347-353
Link Here
|
347 |
if(request_q.IsEmpty() && !m_state.remote_choked){ |
496 |
if(request_q.IsEmpty() && !m_state.remote_choked){ |
348 |
if( RequestPiece() < 0 ) return -1; |
497 |
if( RequestPiece() < 0 ) return -1; |
349 |
} |
498 |
} |
350 |
} |
499 |
} else |
|
|
500 |
if(m_state.local_interested && SetLocal(M_NOT_INTERESTED) < 0) return -1; |
351 |
|
501 |
|
352 |
if(!request_q.IsEmpty()) StartDLTimer(); |
502 |
if(!request_q.IsEmpty()) StartDLTimer(); |
353 |
return 0; |
503 |
return 0; |
Lines 355-360
Link Here
|
355 |
|
505 |
|
356 |
void btPeer::CloseConnection() |
506 |
void btPeer::CloseConnection() |
357 |
{ |
507 |
{ |
|
|
508 |
if(arg_verbose) fprintf(stderr, "%p closed\n", this); |
358 |
if( P_FAILED != m_status ){ |
509 |
if( P_FAILED != m_status ){ |
359 |
m_status = P_FAILED; |
510 |
m_status = P_FAILED; |
360 |
stream.Close(); |
511 |
stream.Close(); |
Lines 364-376
Link Here
|
364 |
int btPeer::HandShake() |
515 |
int btPeer::HandShake() |
365 |
{ |
516 |
{ |
366 |
ssize_t r = stream.Feed(); |
517 |
ssize_t r = stream.Feed(); |
367 |
if( r < 0 ) return -1; |
518 |
if( r < 0 ){ |
|
|
519 |
// if(arg_verbose) fprintf(stderr, "hs: r<0 (%d)\n", r); |
520 |
return -1; |
521 |
} |
368 |
else if( r < 68 ){ |
522 |
else if( r < 68 ){ |
369 |
if(r && memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),r) != 0) return -1; |
523 |
if(r >= 21){ // Ignore 8 reserved bytes following protocol ID. |
|
|
524 |
if( memcmp(stream.in_buffer.BasePointer()+20, |
525 |
BTCONTENT.GetShakeBuffer()+20, (r<28) ? r-20 : 8) != 0 ){ |
526 |
if(arg_verbose){ |
527 |
if( r>48 ) fprintf( stderr, "\npeer %p gave 0x", this); |
528 |
else fprintf( stderr, "\npeer gave 0x" ); |
529 |
for(int i=20; i<r && i<27; i++) fprintf(stderr, "%2.2hx", |
530 |
(u_short)(u_char)(stream.in_buffer.BasePointer()[i])); |
531 |
fprintf( stderr, " as reserved bytes (partial)\n" ); |
532 |
} |
533 |
memcpy(stream.in_buffer.BasePointer()+20, BTCONTENT.GetShakeBuffer()+20, |
534 |
(r<28) ? r-20 : 8); |
535 |
} |
536 |
} |
537 |
if(r && memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(), |
538 |
(r<48) ? r : 48) != 0){ |
539 |
if(arg_verbose){ |
540 |
fprintf(stderr, "\nmine: 0x"); |
541 |
for(int i=0; i<r && i<48; i++) fprintf(stderr, "%2.2hx", |
542 |
(u_short)(u_char)(BTCONTENT.GetShakeBuffer()[i])); |
543 |
fprintf(stderr, "\npeer: 0x"); |
544 |
for(int i=0; i<r && i<48; i++) fprintf(stderr, "%2.2hx", |
545 |
(u_short)(u_char)(stream.in_buffer.BasePointer()[i])); |
546 |
fprintf(stderr, "\n"); |
547 |
fprintf(stderr, "peer is %.8s\n", stream.in_buffer.BasePointer()+48); |
548 |
} |
549 |
return -1; |
550 |
} |
370 |
return 0; |
551 |
return 0; |
371 |
} |
552 |
} |
372 |
|
553 |
|
373 |
if( memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),48) != 0 ) return -1; |
554 |
// If the reserved bytes differ, make them the same. |
|
|
555 |
// If they mean anything important, the handshake is likely to fail anyway. |
556 |
if( memcmp(stream.in_buffer.BasePointer()+20, BTCONTENT.GetShakeBuffer()+20, |
557 |
8) != 0 ){ |
558 |
if(arg_verbose){ |
559 |
fprintf(stderr, "\npeer %p gave 0x", this); |
560 |
for(int i=20; i<27; i++) fprintf(stderr, "%2.2hx", |
561 |
(u_short)(u_char)(stream.in_buffer.BasePointer()[i])); |
562 |
fprintf( stderr, " as reserved bytes\n" ); |
563 |
} |
564 |
memcpy(stream.in_buffer.BasePointer()+20, BTCONTENT.GetShakeBuffer()+20, 8); |
565 |
} |
566 |
if( memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),48) != 0 ){ |
567 |
if(arg_verbose){ |
568 |
fprintf(stderr, "\nmine: 0x"); |
569 |
for(int i=0; i<48; i++) fprintf(stderr, "%2.2hx", |
570 |
(u_short)(u_char)(BTCONTENT.GetShakeBuffer()[i])); |
571 |
fprintf(stderr, "\npeer: 0x"); |
572 |
for(int i=0; i<48; i++) fprintf(stderr, "%2.2hx", |
573 |
(u_short)(u_char)(stream.in_buffer.BasePointer()[i])); |
574 |
fprintf(stderr, "\n"); |
575 |
} |
576 |
return -1; |
577 |
} |
578 |
|
579 |
if(arg_verbose){ |
580 |
fprintf(stderr, "Peer %p ID: ", this); |
581 |
for(int i=48; i<60; i++){ |
582 |
if( isprint(stream.in_buffer.BasePointer()[i]) ) |
583 |
fprintf(stderr, "%c", stream.in_buffer.BasePointer()[i]); |
584 |
else break; |
585 |
} |
586 |
fprintf(stderr, "\n"); |
587 |
} |
374 |
|
588 |
|
375 |
// ignore peer id verify |
589 |
// ignore peer id verify |
376 |
if( !BTCONTENT.pBF->IsEmpty()){ |
590 |
if( !BTCONTENT.pBF->IsEmpty()){ |
Lines 395-404
Link Here
|
395 |
return stream.Send_Buffer((char*)BTCONTENT.GetShakeBuffer(),68); |
609 |
return stream.Send_Buffer((char*)BTCONTENT.GetShakeBuffer(),68); |
396 |
} |
610 |
} |
397 |
|
611 |
|
398 |
int btPeer::BandWidthLimit() |
612 |
int btPeer::BandWidthLimitUp() |
|
|
613 |
{ |
614 |
if( cfg_max_bandwidth_up <= 0 ) return 0; |
615 |
return ((Self.RateUL()) >= cfg_max_bandwidth_up) ? |
616 |
1:0; |
617 |
} |
618 |
|
619 |
int btPeer::BandWidthLimitDown() |
399 |
{ |
620 |
{ |
400 |
if( cfg_max_bandwidth <= 0 ) return 0; |
621 |
if( cfg_max_bandwidth_down <= 0 ) return 0; |
401 |
return ((Self.RateDL() + Self.RateUL()*2) / 1024 >= cfg_max_bandwidth) ? |
622 |
return ((Self.RateDL()) >= cfg_max_bandwidth_down) ? |
402 |
1:0; |
623 |
1:0; |
403 |
} |
624 |
} |
404 |
|
625 |
|
Lines 406-417
Link Here
|
406 |
{ |
627 |
{ |
407 |
int yn = 0; |
628 |
int yn = 0; |
408 |
if( stream.out_buffer.Count() || // data need send in buffer. |
629 |
if( stream.out_buffer.Count() || // data need send in buffer. |
409 |
(!reponse_q.IsEmpty() && CouldReponseSlice() && !BandWidthLimit()) || |
630 |
(!reponse_q.IsEmpty() && CouldReponseSlice() && ! BandWidthLimitUp()) || |
|
|
631 |
( !m_state.remote_choked && request_q.IsEmpty() |
632 |
&& m_state.local_interested |
633 |
&& !BandWidthLimitDown() && !m_standby ) || // can request a piece. |
410 |
P_CONNECTING == m_status ) // peer is connecting |
634 |
P_CONNECTING == m_status ) // peer is connecting |
411 |
yn = 1; |
635 |
yn = 1; |
412 |
return yn; |
636 |
return yn; |
413 |
} |
637 |
} |
414 |
|
638 |
|
|
|
639 |
int btPeer::NeedRead() |
640 |
{ |
641 |
int yn = 1; |
642 |
if( !request_q.IsEmpty() && BandWidthLimitDown() ) |
643 |
yn = 0; |
644 |
return yn; |
645 |
} |
646 |
|
415 |
int btPeer::CouldReponseSlice() |
647 |
int btPeer::CouldReponseSlice() |
416 |
{ |
648 |
{ |
417 |
if(!m_state.local_choked && |
649 |
if(!m_state.local_choked && |
Lines 453-467
Link Here
|
453 |
{ |
685 |
{ |
454 |
if( stream.out_buffer.Count() && stream.Flush() < 0) return -1; |
686 |
if( stream.out_buffer.Count() && stream.Flush() < 0) return -1; |
455 |
|
687 |
|
456 |
if(! reponse_q.IsEmpty() && CouldReponseSlice() ) { |
688 |
if( !reponse_q.IsEmpty() && CouldReponseSlice() && !BandWidthLimitUp() ) { |
457 |
StartULTimer(); |
689 |
StartULTimer(); |
458 |
Self.StartULTimer(); |
690 |
Self.StartULTimer(); |
459 |
} |
691 |
} |
460 |
|
692 |
|
461 |
for(; !reponse_q.IsEmpty() && CouldReponseSlice(); ) |
693 |
for(; !reponse_q.IsEmpty() && CouldReponseSlice() && !BandWidthLimitUp(); ) |
462 |
if( ReponseSlice() < 0) return -1; |
694 |
if( ReponseSlice() < 0) return -1; |
463 |
|
695 |
|
464 |
return 0; |
696 |
return (!m_state.remote_choked && request_q.IsEmpty()) ? RequestCheck() : 0; |
465 |
} |
697 |
} |
466 |
|
698 |
|
467 |
void btPeer::dump() |
699 |
void btPeer::dump() |