6 #include "./btcontent.h"
7 #include "./msgencode.h"
8 #include "./peerlist.h"
9 #include "./btconfig.h"
13 void btBasic::SetIp(struct sockaddr_in addr)
15 memcpy(&m_sin.sin_addr,&addr.sin_addr,sizeof(struct in_addr));
18 void btBasic::SetAddress(struct sockaddr_in addr)
20 memcpy(&m_sin,&addr,sizeof(struct sockaddr_in));
23 int btBasic::IpEquiv(struct sockaddr_in addr)
25 return (memcmp(&m_sin.sin_addr,&addr.sin_addr,sizeof(struct in_addr)) == 0) ?
29 int btPeer::Need_Local_Data()
31 if( m_state.remote_interested && !bitfield.IsFull()){
33 if( BTCONTENT.pBF->IsFull() ) return 1; // i am seed
35 BitField tmpBitfield = *BTCONTENT.pBF;
36 tmpBitfield.Except(bitfield);
37 return tmpBitfield.IsEmpty() ? 0 : 1;
43 int btPeer::Need_Remote_Data()
45 if( BTCONTENT.pBF->IsFull()) return 0;
46 else if( bitfield.IsFull() ) return 1;
48 BitField tmpBitfield = bitfield;
49 tmpBitfield.Except(*BTCONTENT.pBF);
50 return tmpBitfield.IsEmpty() ? 0 : 1;
58 m_status = P_CONNECTING;
59 m_unchoke_timestamp = (time_t) 0;
60 time(&m_last_timestamp);
61 m_state.remote_choked = m_state.local_choked = 1;
62 m_state.remote_interested = m_state.local_interested = 0;
65 m_cached_idx = BTCONTENT.GetNPieces();
68 int btPeer::SetLocal(unsigned char s)
72 if( m_state.local_choked ) return 0;
73 m_state.local_choked = 1;
76 if( !reponse_q.IsEmpty() ) StartULTimer();
77 if( !m_state.local_choked ) return 0;
78 time(&m_unchoke_timestamp);
79 m_state.local_choked = 0;
82 if( m_state.local_interested ) return 0;
83 m_state.local_interested = 1;
85 case M_NOT_INTERESTED:
86 if( !m_state.local_interested ) return 0;
87 m_state.local_interested = 0;
92 return stream.Send_State(s);
95 int btPeer::RequestPiece()
99 PENDINGQUEUE.ReAssign(&request_q,bitfield);
101 if( !request_q.IsEmpty() ) return SendRequest();
103 if( m_cached_idx < BTCONTENT.GetNPieces() ){
105 m_cached_idx = BTCONTENT.GetNPieces();
106 if( !BTCONTENT.pBF->IsSet(idx) &&
107 !PENDINGQUEUE.Exist(idx) &&
108 !WORLD.AlreadyRequested(idx) ){
109 return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest();
112 BitField tmpBitField;
113 if( bitfield.IsFull() ){
114 tmpBitField = *BTCONTENT.pBF;
115 tmpBitField.Invert();
117 tmpBitField = bitfield;
118 tmpBitField.Except(*BTCONTENT.pBF);
121 if( !tmpBitField.IsEmpty() ){
122 WORLD.CheckBitField(tmpBitField);
123 if(tmpBitField.IsEmpty()){
125 btPeer *peer = WORLD.Who_Can_Abandon(this);
128 request_q = peer->request_q;
130 if(peer->CancelRequest(request_q.GetHead()) < 0 ||
131 peer->RequestCheck() < 0){
132 peer->CloseConnection();
135 return SendRequest();
139 idx = tmpBitField.Random();
140 return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest();
147 int btPeer::MsgDeliver()
149 size_t r,idx,off,len;
151 char *msgbuf = stream.in_buffer.BasePointer();
153 r = ntohl(*(size_t*) msgbuf);
156 time(&m_last_timestamp);
157 if( !m_f_keepalive ) if( stream.Send_Keepalive() < 0 ) return -1;
159 return (!m_state.remote_choked && request_q.IsEmpty()) ? RequestCheck() : 0;
163 if(H_BASE_LEN != r){ return -1;}
164 m_state.remote_choked = 1;
166 if( !request_q.IsEmpty()){
167 PSLICE ps = request_q.GetHead();
168 PENDINGQUEUE.Pending(&request_q);
169 if( CancelRequest(ps) < 0) return -1;
173 if(H_BASE_LEN != r){return -1;}
174 m_state.remote_choked = 0;
175 return RequestCheck();
178 if(H_BASE_LEN != r){return -1;}
179 m_state.remote_interested = 1;
182 case M_NOT_INTERESTED:
183 if(r != H_BASE_LEN){return -1;}
185 m_state.remote_interested = 0;
188 /* remove peer's reponse queue */
189 if( !reponse_q.IsEmpty()) reponse_q.Empty();
192 if(H_HAVE_LEN != r){return -1;}
194 idx = ntohl(*(size_t*) (msgbuf + 5));
196 if( idx >= BTCONTENT.GetNPieces() || bitfield.IsSet(idx)) return -1;
200 if( bitfield.IsFull() && BTCONTENT.pBF->IsFull() ){ return -2; }
202 if( !BTCONTENT.pBF->IsSet(idx) ) m_cached_idx = idx;
204 return ( !m_state.remote_choked && request_q.IsEmpty() ) ? RequestCheck() : 0;
207 if(H_REQUEST_LEN != r || !m_state.remote_interested){ return -1; }
209 idx = ntohl(*(size_t*)(msgbuf + 5));
211 if( !BTCONTENT.pBF->IsSet(idx) ) return -1;
213 off = ntohl(*(size_t*)(msgbuf + 9));
214 len = ntohl(*(size_t*)(msgbuf + 13));
216 if( !reponse_q.IsValidRequest(idx, off, len) ) return -1;
218 return reponse_q.Add(idx, off, len);
221 if( request_q.IsEmpty() || !m_state.local_interested){
225 return PieceDeliver(r);
228 if( (r - 1) != bitfield.NBytes() || !bitfield.IsEmpty()) return -1;
229 bitfield.SetReferBuffer(msgbuf + 5);
230 if(bitfield.IsFull() && BTCONTENT.pBF->IsFull()) return -2;
234 if(r != H_CANCEL_LEN || !m_state.remote_interested) return -1;
236 idx = ntohl(*(size_t*)(msgbuf + 5));
237 off = ntohl(*(size_t*)(msgbuf + 9));
238 len = ntohl(*(size_t*)(msgbuf + 13));
239 if( reponse_q.Remove(idx,off,len) < 0 ){
243 if( reponse_q.IsEmpty() ) StopULTimer();
246 return -1; // unknow message type
252 int btPeer::ReponseSlice()
256 reponse_q.Peek((size_t*) 0,(size_t*) 0, &len);
258 if(len && stream.out_buffer.LeftSize() <= (len + 13 + 3 * 1024))
261 if(len && stream.out_buffer.LeftSize() > (len + 13 + 3 * 1024)){
263 reponse_q.Pop(&idx,&off,(size_t *) 0);
265 if(BTCONTENT.ReadSlice(BTCONTENT.global_piece_buffer,idx,off,len) != 0 ){
269 Self.DataSended(len);
271 return stream.Send_Piece(idx,off,BTCONTENT.global_piece_buffer,len);
277 int btPeer::SendRequest()
279 PSLICE ps = request_q.GetHead();
280 for( ; ps ; ps = ps->next )
281 if(stream.Send_Request(ps->index,ps->offset,ps->length) < 0){ return -1; }
283 return stream.Flush();
286 int btPeer::CancelRequest(PSLICE ps)
288 for( ; ps; ps = ps->next){
289 if(stream.Send_Cancel(ps->index,ps->offset,ps->length) < 0)
292 return stream.Flush();
295 int btPeer::ReportComplete(size_t idx)
297 if( BTCONTENT.APieceComplete(idx) ){
298 WORLD.Tell_World_I_Have(idx);
299 if( BTCONTENT.pBF->IsFull() ){
301 WORLD.CloseAllConnectionToSeed();
305 return (P_FAILED == m_status) ? -1 : RequestCheck();
308 int btPeer::PieceDeliver(size_t mlen)
311 char *msgbuf = stream.in_buffer.BasePointer();
313 idx = ntohl(*(size_t*) (msgbuf + 5));
314 off = ntohl(*(size_t*) (msgbuf + 9));
317 if( request_q.Remove(idx,off,len) < 0 ){
322 if(BTCONTENT.WriteSlice((char*)(msgbuf + 13),idx,off,len) < 0){
327 Self.DataRecved(len);
330 /* if piece download complete. */
331 return request_q.IsEmpty() ? ReportComplete(idx) : 0;
334 int btPeer::RequestCheck()
336 if( BandWidthLimit() ) return 0;
338 if( BTCONTENT.pBF->IsFull() ){
339 if( bitfield.IsFull() ){ return -1; }
340 return SetLocal(M_NOT_INTERESTED);
343 if( Need_Remote_Data() ){
344 if(!m_state.local_interested && SetLocal(M_INTERESTED) < 0) return -1;
345 if(request_q.IsEmpty() && !m_state.remote_choked){
346 if( RequestPiece() < 0 ) return -1;
350 if(!request_q.IsEmpty()) StartDLTimer();
354 void btPeer::CloseConnection()
356 if( P_FAILED != m_status ){
362 int btPeer::HandShake()
364 ssize_t r = stream.Feed();
365 if( r < 0 ) return -1;
367 if(r && memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),r) != 0) return -1;
371 if( memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),48) != 0 ) return -1;
373 // ignore peer id verify
374 if( !BTCONTENT.pBF->IsEmpty()){
375 char *bf = new char[BTCONTENT.pBF->NBytes()];
379 BTCONTENT.pBF->WriteToBuffer(bf);
380 r = stream.Send_Bitfield(bf,BTCONTENT.pBF->NBytes());
385 if( stream.in_buffer.PickUp(68) < 0 ) return -1;
386 m_status = P_SUCCESS;
391 int btPeer::Send_ShakeInfo()
393 return stream.Send_Buffer((char*)BTCONTENT.GetShakeBuffer(),68);
396 int btPeer::BandWidthLimit()
398 if( cfg_max_bandwidth <= 0 ) return 0;
399 return ((Self.RateDL() + Self.RateUL()*2) / 1024 >= cfg_max_bandwidth) ?
403 int btPeer::NeedWrite()
406 if( stream.out_buffer.Count() || // data need send in buffer.
407 (!reponse_q.IsEmpty() && CouldReponseSlice() && !BandWidthLimit()) ||
408 P_CONNECTING == m_status ) // peer is connecting
413 int btPeer::CouldReponseSlice()
415 if(!m_state.local_choked &&
416 (stream.out_buffer.LeftSize() > reponse_q.GetRequestLen() + 4 * 1024 ))
421 int btPeer::AreYouOK()
424 return stream.Send_Keepalive();
427 int btPeer::RecvModule()
429 int f_peer_closed = 0;
432 if ( 64 < m_err_count ) return -1;
436 if( r < 0 && r != -2 )
441 r = stream.HaveMessage();
443 if( r < 0 ) return -1;
444 if(MsgDeliver() < 0 || stream.PickMessage() < 0) return -1;
445 r = stream.HaveMessage();
447 return f_peer_closed ? -1 : 0;
450 int btPeer::SendModule()
452 if( stream.out_buffer.Count() && stream.Flush() < 0) return -1;
454 if(! reponse_q.IsEmpty() && CouldReponseSlice() ) {
459 for(; !reponse_q.IsEmpty() && CouldReponseSlice(); )
460 if( ReponseSlice() < 0) return -1;