1 Only in ctorrent-1.3.4: README-DNH.TXT
2 diff -u ctorrent-1.3.4.orig/btconfig.cpp ctorrent-1.3.4/btconfig.cpp
3 --- ctorrent-1.3.4.orig/btconfig.cpp 2004-09-09 01:10:51.000000000 +0200
4 +++ ctorrent-1.3.4/btconfig.cpp 2005-08-11 23:45:29.424694440 +0200
8 -size_t cfg_req_slice_size = 32768;
9 +//size_t cfg_req_slice_size = 32768;
10 +size_t cfg_req_slice_size = 16384;
12 size_t cfg_cache_size = 16;
15 int cfg_max_listen_port = 2706;
16 int cfg_min_listen_port = 2106;
18 -int cfg_max_bandwidth = -1;
19 +int cfg_max_bandwidth_down = -1;
20 +int cfg_max_bandwidth_up = -1;
22 time_t cfg_seed_hours = 72;
25 unsigned char arg_flg_check_only = 0;
26 unsigned char arg_flg_exam_only = 0;
27 unsigned char arg_flg_make_torrent = 0;
28 +unsigned char arg_file_to_download = 0;
29 +unsigned char arg_verbose = 0;
31 size_t arg_piece_length = 262144;
32 char *arg_announce = (char*) 0;
33 diff -u ctorrent-1.3.4.orig/btconfig.h ctorrent-1.3.4/btconfig.h
34 --- ctorrent-1.3.4.orig/btconfig.h 2004-09-09 01:10:51.000000000 +0200
35 +++ ctorrent-1.3.4/btconfig.h 2005-08-11 23:45:29.425694288 +0200
37 extern time_t cfg_seed_hours;
39 extern int cfg_max_bandwidth;
40 +extern int cfg_max_bandwidth_down;
41 +extern int cfg_max_bandwidth_up;
43 // arguments global value
44 extern char *arg_metainfo_file;
46 extern unsigned char arg_flg_check_only;
47 extern unsigned char arg_flg_exam_only;
48 extern unsigned char arg_flg_make_torrent;
49 +extern unsigned char arg_file_to_download;
50 +extern unsigned char arg_verbose;
52 extern size_t arg_piece_length;
53 extern char *arg_announce;
54 diff -u ctorrent-1.3.4.orig/btcontent.cpp ctorrent-1.3.4/btcontent.cpp
55 --- ctorrent-1.3.4.orig/btcontent.cpp 2004-09-09 01:10:51.000000000 +0200
56 +++ ctorrent-1.3.4/btcontent.cpp 2005-08-11 23:45:29.425694288 +0200
60 #include "httpencode.h"
63 #define meta_str(keylist,pstr,pint) decode_query(b,flen,(keylist),(pstr),(pint),QUERY_STR)
64 #define meta_int(keylist,pint) decode_query(b,flen,(keylist),(const char**) 0,(pint),QUERY_INT)
66 m_announce = global_piece_buffer = (char*) 0;
67 m_hash_table = (unsigned char *) 0;
69 + pBFilter = (BitField*) 0;
70 m_create_date = m_seed_timestamp = (time_t) 0;
71 time(&m_start_timestamp);
72 m_cache = (BTCACHE*) 0;
74 if( m_btfiles.BuildFromMI(b, flen, saveas) < 0) ERR_RETURN();
80 if( arg_flg_exam_only ) return 0;
82 if( !pBF ) ERR_RETURN();
85 + //create the file filter
86 + pBFilter = new BitField(m_npieces);
88 + if( !pBFilter ) ERR_RETURN();
90 + if(arg_file_to_download>0){
91 + m_btfiles.SetFilter(arg_file_to_download,pBFilter,m_piece_length);
96 m_left_bytes = m_btfiles.GetTotalLength() / m_piece_length;
97 if( m_btfiles.GetTotalLength() % m_piece_length ) m_left_bytes++;
98 if( m_left_bytes != m_npieces ) ERR_RETURN();
101 ssize_t btContent::ReadSlice(char *buf,size_t idx,size_t off,size_t len)
103 - u_int64_t offset = idx * m_piece_length + off;
105 + u_int64_t offset = (u_int64_t)idx * (u_int64_t)m_piece_length + (u_int64_t)off;
107 if( !m_cache_size ) return m_btfiles.IO(buf, offset, len, 0);
111 ssize_t btContent::WriteSlice(char *buf,size_t idx,size_t off,size_t len)
113 - u_int64_t offset = (u_int64_t)(idx * m_piece_length + off);
114 + //u_int64_t offset = (u_int64_t)(idx * m_piece_length + off);
116 + u_int64_t offset = (u_int64_t)idx * (u_int64_t)m_piece_length + (u_int64_t)off;
118 + // printf("\nOffset-write: %lu - Piece:%lu\n",offset,(unsigned long)idx);
120 if( !m_cache_size ) return m_btfiles.IO(buf, offset, len, 1);
123 if( !percent ) percent = 1;
125 for( ; idx < m_npieces; idx++){
126 - if( GetHashValue(idx, md) == 0 && memcmp(md, m_hash_table + idx * 20, 20) == 0){
127 - m_left_bytes -= GetPieceLength(idx);
129 + if( GetHashValue(idx, md) == 0 && memcmp(md, m_hash_table + idx * 20, 20) == 0){
130 + m_left_bytes -= GetPieceLength(idx);
133 if(idx % percent == 0){
134 printf("\rCheck exist: %d/%d",idx,pBF->NBits());
136 fprintf(stderr,"warn,piece %d hash check failed.\n",idx);
141 m_left_bytes -= GetPieceLength(idx);
146 if( !m_seed_timestamp ){
157 +size_t btContent::getFilePieces(unsigned char nfile){
158 + return m_btfiles.getFilePieces(nfile);
162 +void btContent::SetFilter(){
163 + m_btfiles.SetFilter(arg_file_to_download,pBFilter,m_piece_length);
165 diff -u ctorrent-1.3.4.orig/btcontent.h ctorrent-1.3.4/btcontent.h
166 --- ctorrent-1.3.4.orig/btcontent.h 2004-09-09 01:10:51.000000000 +0200
167 +++ ctorrent-1.3.4/btcontent.h 2005-08-11 23:45:29.426694136 +0200
172 + BitField *pBFilter;
173 char *global_piece_buffer;
179 int SeedTimeout(const time_t *pnow);
183 + size_t getFilePieces(unsigned char nfile);
187 extern btContent BTCONTENT;
188 diff -u ctorrent-1.3.4.orig/btfiles.cpp ctorrent-1.3.4/btfiles.cpp
189 --- ctorrent-1.3.4.orig/btfiles.cpp 2004-09-09 01:10:51.000000000 +0200
190 +++ ctorrent-1.3.4/btfiles.cpp 2005-08-11 23:45:29.426694136 +0200
192 pos = (size_t) (off - (n - pbf->bf_length));
196 if( !pbf->bf_flag_opened ){
197 if( _btf_open(pbf) < 0 ) return -1;
200 if( 1 != fread(buf,nio,1,pbf->bf_fp) ) return -1;
202 if( 1 != fwrite(buf,nio,1,pbf->bf_fp) ) return -1;
203 + fflush(pbf->bf_fp);
211 - if( !getwd(full_cur) ) return -1;
212 + if( !getcwd(full_cur,MAXPATHLEN) ) return -1;
215 strcpy(fn, full_cur);
218 }else if( S_IFDIR & sb.st_mode ){
220 - if( !getwd(wd) ) return -1;
221 + if( !getcwd(wd,MAXPATHLEN) ) return -1;
222 m_directory = new char[strlen(pathname) + 1];
224 if( !m_directory ) return -1;
231 +void btFiles::SetFilter(int nfile, BitField *pFilter, size_t pieceLength)
235 + BTFILE *p = m_btfhead;
237 + u_int64_t sizeBuffer=0;
242 + for( ; p ; p = p->bf_next ){
245 + start = sizeBuffer/pieceLength;
246 + stop = (sizeBuffer+p->bf_length)/pieceLength;
247 + printf ("\rDownloading file: <%d> %s \nPieces: %d - %d (%d)\n",nfile,p->bf_filename,start,stop,stop-start+1);
248 + p->bf_npieces = stop-start+1;
249 + for(index=sizeBuffer/pieceLength;index<=(sizeBuffer+p->bf_length)/pieceLength;index++){
250 + pFilter->UnSet(index);
253 + sizeBuffer+=(u_int64_t) p->bf_length;
256 + printf("\nEnd of files list. Resuming normal behaviour\n");
258 + arg_file_to_download = 0;
262 +size_t btFiles::getFilePieces(unsigned char nfile)
264 + //returns the pieces of the file already gotten
266 + BTFILE *p = m_btfhead;
269 + for( ; p ; p = p->bf_next ){
271 + return p->bf_npieces;
280 diff -u ctorrent-1.3.4.orig/btfiles.h ctorrent-1.3.4/btfiles.h
281 --- ctorrent-1.3.4.orig/btfiles.h 2004-09-09 01:10:51.000000000 +0200
282 +++ ctorrent-1.3.4/btfiles.h 2005-08-11 23:45:29.427693984 +0200
285 #include <sys/types.h>
288 +#include "bitfield.h"
289 +extern unsigned char arg_file_to_download;
293 typedef struct _btfile{
296 size_t bf_completed; // already downloaded length
298 + size_t bf_npieces; //number of pieces
300 unsigned char bf_flag_opened:1;
301 unsigned char bf_flag_need:1;
302 unsigned char bf_reserved:6;
304 u_int64_t GetTotalLength() const { return m_total_files_length; }
305 ssize_t IO(char *buf, u_int64_t off, size_t len, const int iotype);
306 size_t FillMetaInfo(FILE* fp);
308 + void SetFilter(int nfile, BitField *pFilter,size_t pieceLength);
309 + size_t getFilePieces(unsigned char nfile);
314 diff -u ctorrent-1.3.4.orig/btrequest.cpp ctorrent-1.3.4/btrequest.cpp
315 --- ctorrent-1.3.4.orig/btrequest.cpp 2004-09-09 01:10:51.000000000 +0200
316 +++ ctorrent-1.3.4/btrequest.cpp 2005-08-11 23:45:29.427693984 +0200
318 rq.rq_head = (PSLICE) 0;
321 +int RequestQueue::CopyShuffle(RequestQueue &rq)
325 + if( rq_head ) _empty_slice_list(&rq_head);
327 + if( rq.IsEmpty() ) return 0;
328 + for (ps = rq.GetHead(); ps; ps = ps->next) {
330 + if (Add(ps->index, ps->offset, ps->length) < 0) return -1;
332 + else if (Insert(ps->index, ps->offset, ps->length) < 0) return -1;
337 +size_t RequestQueue::Qsize()
340 + PSLICE n = rq_head;
341 + PSLICE u = (PSLICE) 0;
343 + for( ; n ; u = n,n = u->next) cnt++; // move to end
347 +int RequestQueue::Insert(size_t idx,size_t off,size_t len)
350 + PSLICE n = rq_head;
351 + PSLICE u = (PSLICE) 0;
353 + for( ; n ; u = n,n = u->next) cnt++; // move to end (count)
355 + if( cnt >= cfg_req_queue_length ) return -1; // already full
360 + if( !n ) return -1;
373 int RequestQueue::Add(size_t idx,size_t off,size_t len)
381 +int PendingQueue::Delete(size_t idx)
384 + for ( ; i < PENDING_QUEUE_SIZE && pq_count; i++){
385 + if( (PSLICE) 0 != pending_array[i] && idx == pending_array[i]->index){
386 + delete pending_array[i];
387 + pending_array[i] = (PSLICE) 0;
393 +int PendingQueue::DeleteSlice(size_t idx, size_t off, size_t len)
397 + for ( ; i < PENDING_QUEUE_SIZE && pq_count; i++){
398 + if( (PSLICE) 0 != pending_array[i] && idx == pending_array[i]->index){
399 + //check if off & len match any slice
400 + //remove the slice if so
401 + rq.SetHead(pending_array[i]);
402 + if( rq.Remove(idx, off, len) == 0 )
403 + pending_array[i] = rq.GetHead();
410 diff -u ctorrent-1.3.4.orig/btrequest.h ctorrent-1.3.4/btrequest.h
411 --- ctorrent-1.3.4.orig/btrequest.h 2004-09-09 01:10:51.000000000 +0200
412 +++ ctorrent-1.3.4/btrequest.h 2005-08-11 23:45:29.427693984 +0200
414 int IsValidRequest(size_t idx,size_t off,size_t len);
416 void operator=(RequestQueue &rq);
417 + int CopyShuffle(RequestQueue &rq);
420 int IsEmpty() const { return rq_head ? 0 : 1; }
422 + int Insert(size_t idx,size_t off,size_t len);
423 int Add(size_t idx,size_t off,size_t len);
424 int Remove(size_t idx,size_t off,size_t len);
427 int Pending(RequestQueue *prq);
428 int ReAssign(RequestQueue *prq, BitField &bf);
429 int Exist(size_t idx);
430 + int Delete(size_t idx);
431 + int DeleteSlice(size_t idx, size_t off, size_t len);
434 extern PendingQueue PENDINGQUEUE;
435 diff -u ctorrent-1.3.4.orig/btstream.cpp ctorrent-1.3.4/btstream.cpp
436 --- ctorrent-1.3.4.orig/btstream.cpp 2004-09-09 01:10:51.000000000 +0200
437 +++ ctorrent-1.3.4/btstream.cpp 2005-08-11 23:45:29.428693832 +0200
439 #include <arpa/inet.h>
440 #include "btstream.h"
442 #include "msgencode.h"
443 #include "btconfig.h"
446 ssize_t btStream::Send_State(unsigned char state)
448 char msg[H_BASE_LEN + 4];
449 - *(size_t*)msg = htonl(H_BASE_LEN);
451 + set_nl(msg, H_BASE_LEN);
452 msg[4] = (char)state;
453 return out_buffer.PutFlush(sock,msg,H_BASE_LEN + 4);
456 ssize_t btStream::Send_Have(size_t idx)
458 char msg[H_HAVE_LEN + 4];
459 - size_t *p = (size_t*)msg;
461 - *p = htonl(H_HAVE_LEN);
462 + set_nl(msg, H_HAVE_LEN);
463 msg[4] = (char)M_HAVE;
464 - p = (size_t*)(msg + 5);
466 + set_nl(msg + 5, idx);
468 return out_buffer.PutFlush(sock,msg,H_HAVE_LEN + 4);
471 ssize_t btStream::Send_Cancel(size_t idx,size_t off,size_t len)
473 char msg[H_CANCEL_LEN + 4];
474 - size_t *p = (size_t*)msg;
476 - *p = htonl(H_CANCEL_LEN);
477 + set_nl(msg, H_CANCEL_LEN);
479 - p = (size_t*)(msg + 5);
480 - *p = htonl(idx); p++;
481 - *p = htonl(off); p++;
483 + set_nl(msg + 5, idx);
484 + set_nl(msg + 9, off);
485 + set_nl(msg + 13, len);
486 return out_buffer.Put(sock,msg,H_CANCEL_LEN + 4);
490 ssize_t btStream::Send_Request(size_t idx, size_t off,size_t len)
492 char msg[H_REQUEST_LEN + 4];
493 - size_t *p = (size_t*) msg;
495 - *p = htonl(H_REQUEST_LEN);
496 + set_nl(msg, H_REQUEST_LEN);
497 msg[4] = (char)M_REQUEST;
498 - p = (size_t*)(msg + 5);
499 - *p = htonl(idx); p++;
500 - *p = htonl(off); p++;
502 + set_nl(msg + 5, idx);
503 + set_nl(msg + 9, off);
504 + set_nl(msg + 13, len);
505 return out_buffer.Put(sock,msg,H_REQUEST_LEN + 4);
509 // if message arrived.
511 if( 4 <= in_buffer.Count() ){
512 - r = ntohl(*(size_t*)in_buffer.BasePointer());
513 + r = get_nl(in_buffer.BasePointer());
514 if( (cfg_max_slice_size + H_PIECE_LEN + 4) < r) return -1; //message too long
515 if( (r + 4) <= in_buffer.Count() ) return 1;
517 diff -u ctorrent-1.3.4.orig/ctorrent.cpp ctorrent-1.3.4/ctorrent.cpp
518 --- ctorrent-1.3.4.orig/ctorrent.cpp 2004-09-09 01:10:51.000000000 +0200
519 +++ ctorrent-1.3.4/ctorrent.cpp 2005-08-11 23:45:29.428693832 +0200
523 signal(SIGPIPE,SIG_IGN);
524 - signal(SIGINT,sigint_catch);
525 + signal(SIGINT,sig_catch);
526 + signal(SIGTERM,sig_catch);
529 + if( cfg_cache_size ) BTCONTENT.FlushCache();
530 + if( arg_bitfield_file ) BTCONTENT.pBF->WriteToFile(arg_bitfield_file);
536 int param_check(int argc, char **argv)
539 - while ( ( c = getopt(argc,argv,"b:B:cC:e:fl:M:m:P:p:s:tu:xhH")) != -1)
540 + while ( ( c = getopt(argc,argv,"b:cC:D:e:fl:M:m:n:P:p:s:tu:U:vxhH")) != -1)
543 arg_bitfield_file = new char[strlen(optarg) + 1];
544 @@ -150,14 +154,23 @@
548 + case 'n': // Which file download
549 + arg_file_to_download = atoi(optarg);
553 case 'f': // force seed mode, skip sha1 check when startup.
554 arg_flg_force_seed_mode = 1;
558 - cfg_max_bandwidth = atoi(optarg);
560 + cfg_max_bandwidth_down = (int)(strtod(optarg, NULL) * 1024);
564 + cfg_max_bandwidth_up = (int)(strtod(optarg, NULL) * 1024);
569 if (l > MAX_PF_LEN) {printf("-P arg must be 8 or less characters\n"); exit(1);}
571 arg_flg_exam_only = 1;
582 fprintf(stderr,"-h/-H\t\tShow this message.\n");
583 fprintf(stderr,"-x\t\tDecode metainfo(torrent) file only, don't download.\n");
584 fprintf(stderr,"-c\t\tCheck exist only. don't download.\n");
585 + fprintf(stderr,"-v\t\tVerbose output (for debugging).\n");
586 fprintf(stderr,"\nDownload Options:\n");
587 fprintf(stderr,"-e int\t\tExit while seed <int> hours later. (default 72 hours)\n");
588 fprintf(stderr,"-p port\t\tListen port. (default 2706 -> 2106)\n");
590 fprintf(stderr,"-b bf_filename\tBit field filename. (use it carefully)\n");
591 fprintf(stderr,"-M max_peers\tMax peers count.\n");
592 fprintf(stderr,"-m min_peers\tMin peers count.\n");
593 - fprintf(stderr,"-B rate\t\tMax bandwidth (unit KB/s)\n");
594 + fprintf(stderr,"-n file_number\tWhich file download.\n");
595 + fprintf(stderr,"-D rate\t\tMax bandwidth down (unit KB/s)\n");
596 + fprintf(stderr,"-U rate\t\tMax bandwidth up (unit KB/s)\n");
597 fprintf(stderr,"-P peer_id\tSet Peer ID ["PEER_PFX"]\n");
598 fprintf(stderr,"\nMake metainfo(torrent) file Options:\n");
599 fprintf(stderr,"-t\t\tWith make torrent. must specify this option.\n");
600 diff -u ctorrent-1.3.4.orig/downloader.cpp ctorrent-1.3.4/downloader.cpp
601 --- ctorrent-1.3.4.orig/downloader.cpp 2004-09-09 01:10:51.000000000 +0200
602 +++ ctorrent-1.3.4/downloader.cpp 2005-08-11 23:45:29.429693680 +0200
612 - if( BTCONTENT.SeedTimeout(&now) ) break;
613 + if( !stopped && BTCONTENT.SeedTimeout(&now) ) {
614 + Tracker.SetStoped();
618 FD_ZERO(&rfd); FD_ZERO(&wfd);
619 maxfd = Tracker.IntervalCheck(&now,&rfd, &wfd);
621 if(T_FREE != Tracker.GetStatus()) Tracker.SocketReady(&rfd,&wfd,&nfds);
622 if( nfds ) WORLD.AnyPeerReady(&rfd,&wfd,&nfds);
625 + } while(Tracker.GetStatus() != T_FINISHED);
627 diff -u ctorrent-1.3.4.orig/httpencode.cpp ctorrent-1.3.4/httpencode.cpp
628 --- ctorrent-1.3.4.orig/httpencode.cpp 2004-09-09 01:10:51.000000000 +0200
629 +++ ctorrent-1.3.4/httpencode.cpp 2005-08-11 23:45:29.429693680 +0200
633 if( *p != '/' ) return -1;
634 - for( ; *p && *p != '?'; p++,path++) *path = *p;
635 + for( ; *p; p++,path++) *path = *p;
639 diff -u ctorrent-1.3.4.orig/httpencode.h ctorrent-1.3.4/httpencode.h
640 --- ctorrent-1.3.4.orig/httpencode.h 2004-09-09 01:10:51.000000000 +0200
641 +++ ctorrent-1.3.4/httpencode.h 2005-08-11 23:45:29.429693680 +0200
645 #define REQ_URL_P1_FMT "GET %s?info_hash=%s&peer_id=%s&port=%d"
646 -#define REQ_URL_P2_FMT "%s&uploaded=%d&downloaded=%d&left=%d&event=%s&compact=1 HTTP/1.0"
647 -#define REQ_URL_P3_FMT "%s&uploaded=%d&downloaded=%d&left=%d&compact=1 HTTP/1.0"
648 +//#define REQ_URL_P2_FMT "%s&uploaded=%d&downloaded=%d&left=%d&event=%s&compact=1 HTTP/1.0"
649 +//#define REQ_URL_P3_FMT "%s&uploaded=%d&downloaded=%d&left=%d&compact=1 HTTP/1.0"
650 +#define REQ_URL_P2_FMT "%s&uploaded=%llu&downloaded=%llu&left=%llu&compact=1&event=%s&numwant=%u HTTP/1.0"
651 +#define REQ_URL_P3_FMT "%s&uploaded=%llu&downloaded=%llu&left=%llu&compact=1&numwant=%u HTTP/1.0"
654 char* Http_url_encode(char *s,char *b,size_t n);
655 int Http_url_analyse(char *url,char *host,int *port,char *path);
656 diff -u ctorrent-1.3.4.orig/iplist.cpp ctorrent-1.3.4/iplist.cpp
657 --- ctorrent-1.3.4.orig/iplist.cpp 2004-09-09 01:10:51.000000000 +0200
658 +++ ctorrent-1.3.4/iplist.cpp 2005-08-11 23:45:29.429693680 +0200
660 IPLIST *node = ipl_head;
664 ipl_head = node->next;
669 diff -u ctorrent-1.3.4.orig/peer.cpp ctorrent-1.3.4/peer.cpp
670 --- ctorrent-1.3.4.orig/peer.cpp 2004-09-09 01:10:51.000000000 +0200
671 +++ ctorrent-1.3.4/peer.cpp 2005-08-11 23:45:29.431693376 +0200
678 +#include "btstream.h"
679 #include "./btcontent.h"
680 #include "./msgencode.h"
681 #include "./peerlist.h"
682 #include "./btconfig.h"
684 +size_t get_nl(char *sfrom)
686 + unsigned char *from = (unsigned char *)sfrom;
688 + t = (*from++) << 24;
689 + t |= (*from++) << 16;
690 + t |= (*from++) << 8;
695 +void set_nl(char *sto, size_t from)
697 + unsigned char *to = (unsigned char *)sto;
698 + *to++ = (from >> 24) & 0xff;
699 + *to++ = (from >> 16) & 0xff;
700 + *to++ = (from >> 8) & 0xff;
706 void btBasic::SetIp(struct sockaddr_in addr)
709 int btPeer::Need_Remote_Data()
712 if( BTCONTENT.pBF->IsFull()) return 0;
713 else if( bitfield.IsFull() ) return 1;
715 BitField tmpBitfield = bitfield;
716 tmpBitfield.Except(*BTCONTENT.pBF);
717 + tmpBitfield.Except(*BTCONTENT.pBFilter);
718 return tmpBitfield.IsEmpty() ? 0 : 1;
724 m_cached_idx = BTCONTENT.GetNPieces();
728 int btPeer::SetLocal(unsigned char s)
732 if( m_state.local_choked ) return 0;
733 + time(&m_unchoke_timestamp);
734 +// if(arg_verbose) fprintf(stderr, "Choking %p\n", this);
735 + if(arg_verbose) fprintf(stderr, "Choking %p (D=%lluMB@%uK/s)\n", this,
736 + TotalDL() >> 20, RateDL() >> 10);
737 m_state.local_choked = 1;
740 if( !reponse_q.IsEmpty() ) StartULTimer();
741 if( !m_state.local_choked ) return 0;
742 time(&m_unchoke_timestamp);
743 +// if(arg_verbose) fprintf(stderr, "Unchoking %p\n", this);
744 + if(arg_verbose) fprintf(stderr, "Unchoking %p (D=%lluMB@%uK/s)\n", this,
745 + TotalDL() >> 20, RateDL() >> 10);
746 m_state.local_choked = 0;
750 if( m_state.local_interested ) return 0;
751 + if(arg_verbose) fprintf(stderr, "Interested in %p\n", this);
752 m_state.local_interested = 1;
754 case M_NOT_INTERESTED:
755 if( !m_state.local_interested ) return 0;
756 + if(arg_verbose) fprintf(stderr, "Not interested in %p\n", this);
757 m_state.local_interested = 0;
761 int btPeer::RequestPiece()
766 PENDINGQUEUE.ReAssign(&request_q,bitfield);
768 if( !request_q.IsEmpty() ) return SendRequest();
770 - if( m_cached_idx < BTCONTENT.GetNPieces() ){
771 + if( m_cached_idx < BTCONTENT.GetNPieces() && !BTCONTENT.pBF->IsEmpty() ){
772 + // A HAVE msg already selected what we want from this peer
773 + // but ignore it in initial-piece mode.
775 m_cached_idx = BTCONTENT.GetNPieces();
776 if( !BTCONTENT.pBF->IsSet(idx) &&
777 @@ -110,39 +148,72 @@
778 !WORLD.AlreadyRequested(idx) ){
779 return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest();
782 + } // If we didn't want the cached piece, select another.
783 + if( BTCONTENT.pBF->IsEmpty() ){
784 + // If we don't have a complete piece yet, try to get one that's already
785 + // in progress. (Initial-piece mode)
786 + btPeer *peer = WORLD.Who_Can_Duplicate(this, BTCONTENT.GetNPieces());
788 + if(arg_verbose) fprintf( stderr, "Duping: %p to %p (#%u)\n",
789 + peer, this, peer->request_q.GetRequestIdx() );
790 + return (request_q.CopyShuffle(peer->request_q) < 0) ? -1 : SendRequest();
792 + } // Doesn't have a piece that's already in progress--choose another.
793 BitField tmpBitField;
794 if( bitfield.IsFull() ){
796 tmpBitField = *BTCONTENT.pBF;
797 tmpBitField.Invert();
799 tmpBitField = bitfield;
800 tmpBitField.Except(*BTCONTENT.pBF);
802 + // The filter tells what we don't want.
803 + tmpBitField.Except(*BTCONTENT.pBFilter);
804 + // tmpBitField tells what we need from this peer...
806 if( !tmpBitField.IsEmpty() ){
807 - WORLD.CheckBitField(tmpBitField);
808 - if(tmpBitField.IsEmpty()){
810 - btPeer *peer = WORLD.Who_Can_Abandon(this);
812 - peer->StopDLTimer();
813 - request_q = peer->request_q;
815 - if(peer->CancelRequest(request_q.GetHead()) < 0 ||
816 - peer->RequestCheck() < 0){
817 - peer->CloseConnection();
820 - return SendRequest();
823 + BitField tmpBitField2 = tmpBitField;
824 + WORLD.CheckBitField(tmpBitField2);
825 + // [tmpBitField2]... that we haven't requested from anyone.
826 + if(tmpBitField2.IsEmpty()){
827 + // Everything this peer has that I want, I've already requested.
828 + endgame = ( WORLD.Pieces_I_Can_Get() - BTCONTENT.pBF->Count() )
829 + < WORLD.TotalPeers();
830 + if(endgame){ // OK to duplicate a request.
831 +// idx = tmpBitField.Random();
832 + idx = 0; // flag for Who_Can_Duplicate()
833 + btPeer *peer = WORLD.Who_Can_Duplicate(this, idx);
834 + if(arg_verbose) fprintf( stderr, "Duping: %p to %p (#%u)\n",
835 + peer, this, peer->request_q.GetRequestIdx() );
836 + return (request_q.CopyShuffle(peer->request_q) < 0) ?
837 + -1 : SendRequest();
838 + }else{ // not endgame mode
839 + btPeer *peer = WORLD.Who_Can_Abandon(this); // slowest choice
841 + // Cancel a request to the slowest peer & request it from this one.
842 + if(arg_verbose) fprintf( stderr, "Reassigning %p to %p (#%u)\n",
843 + peer, this, peer->request_q.GetRequestIdx() );
844 + peer->StopDLTimer();
845 + // RequestQueue class "moves" rather than "copies" in assignment!
846 + request_q = peer->request_q;
848 + if(peer->CancelRequest(request_q.GetHead()) < 0 ||
849 + peer->RequestCheck() < 0){
850 + peer->CloseConnection();
852 + return SendRequest();
853 + }else m_standby = 1; // nothing to do at the moment
856 - idx = tmpBitField.Random();
857 - return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest();
858 + // Request something that we haven't requested yet (most common case).
859 + idx = tmpBitField2.Random();
860 + return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest();
863 + // We don't need anything from the peer. How'd we get here?
864 + return SetLocal(M_NOT_INTERESTED);
870 @@ -152,37 +223,46 @@
872 char *msgbuf = stream.in_buffer.BasePointer();
874 - r = ntohl(*(size_t*) msgbuf);
875 + r = get_nl(msgbuf);
877 + // Don't require keepalives if we're receiving other messages.
878 + time(&m_last_timestamp);
880 - time(&m_last_timestamp);
881 if( !m_f_keepalive ) if( stream.Send_Keepalive() < 0 ) return -1;
883 - return (!m_state.remote_choked && request_q.IsEmpty()) ? RequestCheck() : 0;
888 if(H_BASE_LEN != r){ return -1;}
889 + if(arg_verbose) fprintf(stderr, "%p choked me\n", this);
890 m_state.remote_choked = 1;
892 if( !request_q.IsEmpty()){
893 PSLICE ps = request_q.GetHead();
894 - PENDINGQUEUE.Pending(&request_q);
895 + if( !PENDINGQUEUE.Exist(request_q.GetRequestIdx()) )
896 + PENDINGQUEUE.Pending(&request_q);
897 if( CancelRequest(ps) < 0) return -1;
902 if(H_BASE_LEN != r){return -1;}
903 + if(arg_verbose) fprintf(stderr, "%p unchoked me\n", this);
904 m_state.remote_choked = 0;
905 + if(!request_q.IsEmpty()) // shouldn't happen; maybe peer is confused.
906 + return SendRequest();
907 return RequestCheck();
910 if(H_BASE_LEN != r){return -1;}
911 + if(arg_verbose) fprintf(stderr, "%p is interested\n", this);
912 m_state.remote_interested = 1;
915 case M_NOT_INTERESTED:
916 if(r != H_BASE_LEN){return -1;}
917 + if(arg_verbose) fprintf(stderr, "%p is not interested\n", this);
919 m_state.remote_interested = 0;
921 @@ -190,10 +270,11 @@
922 /* remove peer's reponse queue */
923 if( !reponse_q.IsEmpty()) reponse_q.Empty();
927 if(H_HAVE_LEN != r){return -1;}
929 - idx = ntohl(*(size_t*) (msgbuf + 5));
930 + idx = get_nl(msgbuf + 5);
932 if( idx >= BTCONTENT.GetNPieces() || bitfield.IsSet(idx)) return -1;
934 @@ -201,19 +282,24 @@
936 if( bitfield.IsFull() && BTCONTENT.pBF->IsFull() ){ return -2; }
938 - if( !BTCONTENT.pBF->IsSet(idx) ) m_cached_idx = idx;
939 + if( !BTCONTENT.pBF->IsSet(idx) && !BTCONTENT.pBFilter->IsSet(idx) ){
940 + m_cached_idx = idx;
943 + // if( !BTCONTENT.pBF->IsSet(idx) ) m_cached_idx = idx;
945 - return ( !m_state.remote_choked && request_q.IsEmpty() ) ? RequestCheck() : 0;
946 + // see if we're Interested now
947 + return request_q.IsEmpty() ? RequestCheck() : 0;
950 if(H_REQUEST_LEN != r || !m_state.remote_interested){ return -1; }
952 - idx = ntohl(*(size_t*)(msgbuf + 5));
953 + idx = get_nl(msgbuf + 5);
955 if( !BTCONTENT.pBF->IsSet(idx) ) return -1;
957 - off = ntohl(*(size_t*)(msgbuf + 9));
958 - len = ntohl(*(size_t*)(msgbuf + 13));
959 + off = get_nl(msgbuf + 9);
960 + len = get_nl(msgbuf + 13);
962 if( !reponse_q.IsValidRequest(idx, off, len) ) return -1;
966 if( request_q.IsEmpty() || !m_state.local_interested){
968 + if(arg_verbose) fprintf(stderr,"err: %p (%d) Unwanted piece\n",
969 + this, m_err_count);
972 return PieceDeliver(r);
973 @@ -230,22 +318,28 @@
974 if( (r - 1) != bitfield.NBytes() || !bitfield.IsEmpty()) return -1;
975 bitfield.SetReferBuffer(msgbuf + 5);
976 if(bitfield.IsFull() && BTCONTENT.pBF->IsFull()) return -2;
979 + //This is needed in order to set our Interested state
980 + return RequestCheck(); // fixed client stall
983 if(r != H_CANCEL_LEN || !m_state.remote_interested) return -1;
985 - idx = ntohl(*(size_t*)(msgbuf + 5));
986 - off = ntohl(*(size_t*)(msgbuf + 9));
987 - len = ntohl(*(size_t*)(msgbuf + 13));
988 + idx = get_nl(msgbuf + 5);
989 + off = get_nl(msgbuf + 9);
990 + len = get_nl(msgbuf + 13);
991 if( reponse_q.Remove(idx,off,len) < 0 ){
993 + if(arg_verbose) fprintf(stderr, "err: %p (%d) Bad cancel\n",
994 + this, m_err_count);
997 if( reponse_q.IsEmpty() ) StopULTimer();
1000 - return -1; // unknow message type
1001 + if(arg_verbose) fprintf(stderr, "Unknown message type %u from peer %p\n",
1003 + return 0; // ignore unknown message & continue (forward compatibility)
1007 @@ -279,8 +373,13 @@
1008 int btPeer::SendRequest()
1010 PSLICE ps = request_q.GetHead();
1011 - for( ; ps ; ps = ps->next )
1012 + if(arg_verbose) fprintf(stderr, "Requesting #%u from %p:",
1013 + request_q.GetRequestIdx(), this);
1014 + for( ; ps ; ps = ps->next ){
1015 + if(arg_verbose) fprintf(stderr, ".");
1016 if(stream.Send_Request(ps->index,ps->offset,ps->length) < 0){ return -1; }
1018 + if(arg_verbose) fprintf(stderr, "\n");
1020 return stream.Flush();
1022 @@ -294,16 +393,56 @@
1023 return stream.Flush();
1026 +int btPeer::CancelSliceRequest(size_t idx, size_t off, size_t len)
1030 + for(ps = request_q.GetHead() ; ps; ps = ps->next){
1031 + if( idx == ps->index && off == ps->offset && len == ps->length ){
1032 + if( request_q.Remove(idx,off,len) < 0 ){
1034 + if(arg_verbose) fprintf(stderr,"err: %p (%d) Bad CS remove\n",
1035 + this, m_err_count);
1037 + if(stream.Send_Cancel(idx,off,len) < 0)
1039 + return stream.Flush();
1045 int btPeer::ReportComplete(size_t idx)
1047 if( BTCONTENT.APieceComplete(idx) ){
1048 + if(arg_verbose) fprintf(stderr, "Piece #%u completed\n", idx);
1049 WORLD.Tell_World_I_Have(idx);
1050 + PENDINGQUEUE.Delete(idx);
1051 if( BTCONTENT.pBF->IsFull() ){
1053 WORLD.CloseAllConnectionToSeed();
1057 + if( arg_file_to_download ){
1058 + BitField tmpBitField = *BTCONTENT.pBF;
1059 + tmpBitField.Except(*BTCONTENT.pBFilter);
1061 + while( arg_file_to_download &&
1062 + tmpBitField.Count() >= BTCONTENT.getFilePieces(arg_file_to_download) ){
1063 + //when the file is complete, we go after the next
1064 + ++arg_file_to_download;
1065 + BTCONTENT.FlushCache();
1066 + BTCONTENT.SetFilter();
1067 + tmpBitField = *BTCONTENT.pBF;
1068 + tmpBitField.Except(*BTCONTENT.pBFilter);
1070 + WORLD.CheckInterest();
1074 + if(arg_verbose) fprintf(stderr, "err: %p (%d) Bad complete\n",
1075 + this, m_err_count);
1077 return (P_FAILED == m_status) ? -1 : RequestCheck();
1080 @@ -312,12 +451,14 @@
1082 char *msgbuf = stream.in_buffer.BasePointer();
1084 - idx = ntohl(*(size_t*) (msgbuf + 5));
1085 - off = ntohl(*(size_t*) (msgbuf + 9));
1086 + idx = get_nl(msgbuf + 5);
1087 + off = get_nl(msgbuf + 9);
1090 if( request_q.Remove(idx,off,len) < 0 ){
1092 + if(arg_verbose) fprintf(stderr, "err: %p (%d) Bad remove\n",
1093 + this, m_err_count);
1097 @@ -329,13 +470,21 @@
1098 Self.DataRecved(len);
1101 + // Check for & cancel requests for this slice from other peers in initial
1102 + // and endgame modes.
1103 + if( BTCONTENT.pBF->Count() < 2 ||
1104 + WORLD.Pieces_I_Can_Get() - BTCONTENT.pBF->Count() < WORLD.TotalPeers() ){
1105 + WORLD.CancelSlice(idx, off, len);
1106 + PENDINGQUEUE.DeleteSlice(idx, off, len);
1109 /* if piece download complete. */
1110 return request_q.IsEmpty() ? ReportComplete(idx) : 0;
1113 int btPeer::RequestCheck()
1115 - if( BandWidthLimit() ) return 0;
1116 + if( BandWidthLimitDown() ) return 0;
1118 if( BTCONTENT.pBF->IsFull() ){
1119 if( bitfield.IsFull() ){ return -1; }
1121 if(request_q.IsEmpty() && !m_state.remote_choked){
1122 if( RequestPiece() < 0 ) return -1;
1126 + if(m_state.local_interested && SetLocal(M_NOT_INTERESTED) < 0) return -1;
1128 if(!request_q.IsEmpty()) StartDLTimer();
1132 void btPeer::CloseConnection()
1134 + if(arg_verbose) fprintf(stderr, "%p closed\n", this);
1135 if( P_FAILED != m_status ){
1136 m_status = P_FAILED;
1138 @@ -364,13 +515,76 @@
1139 int btPeer::HandShake()
1141 ssize_t r = stream.Feed();
1142 - if( r < 0 ) return -1;
1144 +// if(arg_verbose) fprintf(stderr, "hs: r<0 (%d)\n", r);
1148 - if(r && memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),r) != 0) return -1;
1149 + if(r >= 21){ // Ignore 8 reserved bytes following protocol ID.
1150 + if( memcmp(stream.in_buffer.BasePointer()+20,
1151 + BTCONTENT.GetShakeBuffer()+20, (r<28) ? r-20 : 8) != 0 ){
1153 + if( r>48 ) fprintf( stderr, "\npeer %p gave 0x", this);
1154 + else fprintf( stderr, "\npeer gave 0x" );
1155 + for(int i=20; i<r && i<27; i++) fprintf(stderr, "%2.2hx",
1156 + (u_short)(u_char)(stream.in_buffer.BasePointer()[i]));
1157 + fprintf( stderr, " as reserved bytes (partial)\n" );
1159 + memcpy(stream.in_buffer.BasePointer()+20, BTCONTENT.GetShakeBuffer()+20,
1160 + (r<28) ? r-20 : 8);
1163 + if(r && memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),
1164 + (r<48) ? r : 48) != 0){
1166 + fprintf(stderr, "\nmine: 0x");
1167 + for(int i=0; i<r && i<48; i++) fprintf(stderr, "%2.2hx",
1168 + (u_short)(u_char)(BTCONTENT.GetShakeBuffer()[i]));
1169 + fprintf(stderr, "\npeer: 0x");
1170 + for(int i=0; i<r && i<48; i++) fprintf(stderr, "%2.2hx",
1171 + (u_short)(u_char)(stream.in_buffer.BasePointer()[i]));
1172 + fprintf(stderr, "\n");
1173 + fprintf(stderr, "peer is %.8s\n", stream.in_buffer.BasePointer()+48);
1180 - if( memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),48) != 0 ) return -1;
1181 + // If the reserved bytes differ, make them the same.
1182 + // If they mean anything important, the handshake is likely to fail anyway.
1183 + if( memcmp(stream.in_buffer.BasePointer()+20, BTCONTENT.GetShakeBuffer()+20,
1186 + fprintf(stderr, "\npeer %p gave 0x", this);
1187 + for(int i=20; i<27; i++) fprintf(stderr, "%2.2hx",
1188 + (u_short)(u_char)(stream.in_buffer.BasePointer()[i]));
1189 + fprintf( stderr, " as reserved bytes\n" );
1191 + memcpy(stream.in_buffer.BasePointer()+20, BTCONTENT.GetShakeBuffer()+20, 8);
1193 + if( memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),48) != 0 ){
1195 + fprintf(stderr, "\nmine: 0x");
1196 + for(int i=0; i<48; i++) fprintf(stderr, "%2.2hx",
1197 + (u_short)(u_char)(BTCONTENT.GetShakeBuffer()[i]));
1198 + fprintf(stderr, "\npeer: 0x");
1199 + for(int i=0; i<48; i++) fprintf(stderr, "%2.2hx",
1200 + (u_short)(u_char)(stream.in_buffer.BasePointer()[i]));
1201 + fprintf(stderr, "\n");
1207 + fprintf(stderr, "Peer %p ID: ", this);
1208 + for(int i=48; i<60; i++){
1209 + if( isprint(stream.in_buffer.BasePointer()[i]) )
1210 + fprintf(stderr, "%c", stream.in_buffer.BasePointer()[i]);
1213 + fprintf(stderr, "\n");
1216 // ignore peer id verify
1217 if( !BTCONTENT.pBF->IsEmpty()){
1218 @@ -395,10 +609,17 @@
1219 return stream.Send_Buffer((char*)BTCONTENT.GetShakeBuffer(),68);
1222 -int btPeer::BandWidthLimit()
1223 +int btPeer::BandWidthLimitUp()
1225 + if( cfg_max_bandwidth_up <= 0 ) return 0;
1226 + return ((Self.RateUL()) >= cfg_max_bandwidth_up) ?
1230 +int btPeer::BandWidthLimitDown()
1232 - if( cfg_max_bandwidth <= 0 ) return 0;
1233 - return ((Self.RateDL() + Self.RateUL()*2) / 1024 >= cfg_max_bandwidth) ?
1234 + if( cfg_max_bandwidth_down <= 0 ) return 0;
1235 + return ((Self.RateDL()) >= cfg_max_bandwidth_down) ?
1239 @@ -406,12 +627,23 @@
1242 if( stream.out_buffer.Count() || // data need send in buffer.
1243 - (!reponse_q.IsEmpty() && CouldReponseSlice() && !BandWidthLimit()) ||
1244 + (!reponse_q.IsEmpty() && CouldReponseSlice() && ! BandWidthLimitUp()) ||
1245 + ( !m_state.remote_choked && request_q.IsEmpty()
1246 + && m_state.local_interested
1247 + && !BandWidthLimitDown() && !m_standby ) || // can request a piece.
1248 P_CONNECTING == m_status ) // peer is connecting
1253 +int btPeer::NeedRead()
1256 + if( !request_q.IsEmpty() && BandWidthLimitDown() )
1261 int btPeer::CouldReponseSlice()
1263 if(!m_state.local_choked &&
1264 @@ -453,15 +685,15 @@
1266 if( stream.out_buffer.Count() && stream.Flush() < 0) return -1;
1268 - if(! reponse_q.IsEmpty() && CouldReponseSlice() ) {
1269 + if( !reponse_q.IsEmpty() && CouldReponseSlice() && !BandWidthLimitUp() ) {
1271 Self.StartULTimer();
1274 - for(; !reponse_q.IsEmpty() && CouldReponseSlice(); )
1275 + for(; !reponse_q.IsEmpty() && CouldReponseSlice() && !BandWidthLimitUp(); )
1276 if( ReponseSlice() < 0) return -1;
1279 + return (!m_state.remote_choked && request_q.IsEmpty()) ? RequestCheck() : 0;
1283 diff -u ctorrent-1.3.4.orig/peer.h ctorrent-1.3.4/peer.h
1284 --- ctorrent-1.3.4.orig/peer.h 2004-09-09 01:10:51.000000000 +0200
1285 +++ ctorrent-1.3.4/peer.h 2005-08-11 23:45:29.432693224 +0200
1287 unsigned char reserved:4; /* unused */
1290 +size_t get_nl(char *from);
1291 +void set_nl(char *to, size_t from);
1298 size_t m_cached_idx;
1302 int PieceDeliver(size_t mlen);
1303 int ReportComplete(size_t idx);
1305 int CouldReponseSlice();
1307 int BandWidthLimit();
1308 + int BandWidthLimitUp();
1309 + int BandWidthLimitDown();
1313 @@ -118,10 +124,12 @@
1314 int Is_Local_UnChoked() const { return m_state.local_choked ? 0 : 1; }
1315 int SetLocal(unsigned char s);
1317 + int CancelSliceRequest(size_t idx, size_t off, size_t len);
1319 void SetStatus(unsigned char s){ m_status = s; }
1320 unsigned char GetStatus() const { return m_status; }
1325 void CloseConnection();
1326 diff -u ctorrent-1.3.4.orig/peerlist.cpp ctorrent-1.3.4/peerlist.cpp
1327 --- ctorrent-1.3.4.orig/peerlist.cpp 2004-09-09 01:10:51.000000000 +0200
1328 +++ ctorrent-1.3.4/peerlist.cpp 2005-08-11 23:45:29.433693072 +0200
1330 #define MAX_UNCHOKE 3
1331 #define UNCHOKE_INTERVAL 10
1333 +#define OPT_INTERVAL 30
1335 #define KEEPALIVE_INTERVAL 117
1337 #define LISTEN_PORT_MAX 2706
1340 PeerList::PeerList()
1342 - m_unchoke_check_timestamp =
1343 - m_keepalive_check_timestamp = time((time_t*) 0);
1344 + m_unchoke_check_timestamp =
1345 + m_keepalive_check_timestamp =
1346 + m_opt_timestamp = time((time_t*) 0);
1348 m_head = (PEERNODE*) 0;
1349 m_listen_sock = INVALID_SOCKET;
1350 - m_peers_count = 0;
1351 + m_peers_count = m_seeds_count = 0;
1357 if( setfd_nonblock(sk) < 0) goto err;
1359 + if(arg_verbose) fprintf(stderr, "Connecting to %s:%hu\n",
1360 + inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
1361 if( -1 == (r = connect_nonb(sk,(struct sockaddr*)&addr)) ) return -1;
1364 @@ -182,19 +187,44 @@
1365 if(NewPeer(addr,INVALID_SOCKET) == -4) break;
1369 // show status line.
1370 if( m_pre_dlrate.TimeUsed(pnow) ){
1372 - printf("\r%c %u,[%u/%u/%u],%u,%u | %u,%u E:%u",
1373 + char partial[30] = "";
1374 + if(arg_file_to_download){
1375 + BitField tmpBitField = *BTCONTENT.pBF;
1376 + tmpBitField.Except(*BTCONTENT.pBFilter);
1377 + sprintf( partial, "P:%u/%u ",
1378 + tmpBitField.Count(),
1379 + BTCONTENT.getFilePieces(arg_file_to_download) );
1382 + printf("\r%c %u/%u/%u [%u/%u/%u] %lluMB,%lluMB | %u,%uK/s | %u,%uK E:%u,%u %s%s ",
1383 LIVE_CHAR[m_live_idx],
1387 + m_peers_count - m_seeds_count,
1388 + Tracker.GetPeersCount(),
1390 BTCONTENT.pBF->Count(),
1391 BTCONTENT.pBF->NBits(),
1393 - Self.RateDL(), Self.RateUL(),
1394 - m_pre_dlrate.RateMeasure(Self.GetDLRate()),
1395 - m_pre_ulrate.RateMeasure(Self.GetULRate()),
1396 - Tracker.GetRefuseClick());
1398 + Self.TotalDL() >> 20, Self.TotalUL() >> 20,
1400 + Self.RateDL() >> 10, Self.RateUL() >> 10,
1402 + m_pre_dlrate.RateMeasure(Self.GetDLRate()) >> 10,
1403 + m_pre_ulrate.RateMeasure(Self.GetULRate()) >> 10,
1405 + Tracker.GetRefuseClick(),
1406 + Tracker.GetOkClick(),
1410 + (Tracker.GetStatus()==1) ? "Connecting" :
1411 + ((Tracker.GetStatus()==2) ? "Connected" : "")
1414 m_pre_dlrate = Self.GetDLRate();
1415 m_pre_ulrate = Self.GetULRate();
1416 @@ -214,8 +244,12 @@
1420 - if( f_unchoke_check ) memset(UNCHOKER, 0, (MAX_UNCHOKE + 1) * sizeof(btPeer*));
1421 + if( f_unchoke_check ) {
1422 + memset(UNCHOKER, 0, (MAX_UNCHOKE + 1) * sizeof(btPeer*));
1423 + if (OPT_INTERVAL <= *pnow - m_opt_timestamp) m_opt_timestamp = 0;
1426 + m_seeds_count = 0;
1427 for(p = m_head; p;){
1428 if( PEER_IS_FAILED(p->peer)){
1429 if( pp ) pp->next = p->next; else m_head = p->next;
1430 @@ -225,9 +259,11 @@
1431 if( pp ) p = pp->next; else p = m_head;
1434 + if (p->peer->bitfield.IsFull()) m_seeds_count++;
1435 if( f_keepalive_check ){
1437 if(3 * KEEPALIVE_INTERVAL <= (*pnow - p->peer->GetLastTimestamp())){
1438 + if(arg_verbose) fprintf(stderr, "close: keepalive expired\n");
1439 p->peer->CloseConnection();
1442 @@ -235,28 +271,26 @@
1443 if(PEER_IS_SUCCESS(p->peer) &&
1444 KEEPALIVE_INTERVAL <= (*pnow - p->peer->GetLastTimestamp()) &&
1445 p->peer->AreYouOK() < 0){
1446 + if(arg_verbose) fprintf(stderr, "close: keepalive death\n");
1447 p->peer->CloseConnection();
1452 - if( f_unchoke_check ){
1454 - if(PEER_IS_SUCCESS(p->peer) && p->peer->Need_Local_Data()){
1455 + if( f_unchoke_check && PEER_IS_SUCCESS(p->peer) ){
1457 - if((time_t) 0 == p->peer->GetLastUnchokeTime()){
1458 - if(p->peer->SetLocal(M_UNCHOKE) < 0){
1459 - p->peer->CloseConnection();
1460 - goto skip_continue;
1463 + if( p->peer->Is_Remote_Interested() && p->peer->Need_Local_Data() )
1464 UnChokeCheck(p->peer, UNCHOKER);
1466 + else if(p->peer->SetLocal(M_CHOKE) < 0){
1467 + if(arg_verbose) fprintf(stderr, "close: Can't choke peer\n");
1468 + p->peer->CloseConnection();
1469 + goto skip_continue;
1473 sk = p->peer->stream.GetSocket();
1474 if(maxfd < sk) maxfd = sk;
1476 + if( p->peer->NeedRead() ) FD_SET(sk,rfdp);
1478 if( p->peer->NeedWrite() ) FD_SET(sk,wfdp);
1480 @@ -272,13 +306,26 @@
1483 if( f_unchoke_check ){
1484 +// if (!m_opt_timestamp) m_opt_timestamp = *pnow;
1485 + if(arg_verbose) fprintf(stderr, "\nUnchoker ");
1486 + if (!m_opt_timestamp){
1487 + if(arg_verbose) fprintf(stderr, "(opt) ");
1488 + m_opt_timestamp = *pnow;
1490 for( i = 0; i < MAX_UNCHOKE + 1; i++){
1492 if( (btPeer*) 0 == UNCHOKER[i]) break;
1494 if( PEER_IS_FAILED(UNCHOKER[i]) ) continue;
1497 + fprintf(stderr, "D=%lluMB@%uK/s:U=%lluMB ",
1498 + UNCHOKER[i]->TotalDL() >> 20, UNCHOKER[i]->RateDL() >> 10,
1499 + UNCHOKER[i]->TotalUL() >> 20);
1500 + if( UNCHOKER[i]->bitfield.IsEmpty() ) fprintf(stderr, "(empty) ");
1502 if( UNCHOKER[i]->SetLocal(M_UNCHOKE) < 0){
1503 + if(arg_verbose) fprintf(stderr, "close: Can't unchoke peer\n");
1504 UNCHOKER[i]->CloseConnection();
1508 if( maxfd < sk) maxfd = sk;
1511 + if(arg_verbose) fprintf(stderr, "\n");
1515 @@ -314,6 +362,64 @@
1519 +// Duplicating a request queue that's in progress rather than creating a new
1520 +// one helps avoid requesting slices that we already have.
1521 +// This takes an index parameter to facilitate modification of the function to
1522 +// allow targeting of a specific piece. It's currently only used as a flag to
1523 +// specify endgame or initial-piece mode though.
1524 +btPeer* PeerList::Who_Can_Duplicate(btPeer *proposer, size_t idx)
1527 + btPeer *peer = (btPeer*) 0;
1529 + size_t qsize, mark, bench;
1530 + // In endgame mode, select from peers with the longest request queue.
1531 + // In initial mode, select from peers with the shortest non-empty request
1534 + endgame = idx < BTCONTENT.GetNPieces(); // else initial-piece mode
1535 + if(endgame) mark = 0;
1536 + else mark = cfg_req_queue_length;
1537 + bench = BTCONTENT.GetNPieces();
1539 + for(p = m_head; p; p = p->next){
1540 + if(!PEER_IS_SUCCESS(p->peer) || p->peer == proposer ||
1541 + p->peer->request_q.IsEmpty() ) continue;
1543 + if(proposer->bitfield.IsSet(p->peer->request_q.GetRequestIdx())){
1544 + qsize = p->peer->request_q.Qsize();
1545 + if( (endgame && qsize > mark) || (!endgame && qsize && qsize < mark) ){
1548 + }else if( qsize == mark ){
1549 + if( bench != p->peer->request_q.GetRequestIdx() && random()&01 ){
1550 + bench = peer->request_q.GetRequestIdx();
1559 +void PeerList::CancelSlice(size_t idx, size_t off, size_t len)
1564 + for( p = m_head; p; p = p->next){
1566 + if( !PEER_IS_SUCCESS(p->peer) ) continue;
1568 + if( idx == p->peer->request_q.GetRequestIdx() ) {
1569 + if (p->peer->CancelSliceRequest(idx,off,len) < 0) {
1570 + if(arg_verbose) fprintf(stderr, "close: CancelSlice\n");
1571 + p->peer->CloseConnection();
1577 void PeerList::Tell_World_I_Have(size_t idx)
1580 @@ -330,7 +436,12 @@
1583 if( !p->peer->request_q.IsEmpty() ) p->peer->request_q.Empty();
1584 - if(p->peer->SetLocal(M_NOT_INTERESTED) < 0) p->peer->CloseConnection();
1585 +// if(p->peer->SetLocal(M_NOT_INTERESTED) < 0) p->peer->CloseConnection();
1586 + if(p->peer->SetLocal(M_NOT_INTERESTED) < 0) {
1588 + fprintf(stderr, "close: Can't set self not interested (T_W_I_H)\n");
1589 + p->peer->CloseConnection();
1594 @@ -474,15 +585,20 @@
1597 if(FD_ISSET(sk,rfdp)){ // connect failed.
1600 peer->CloseConnection();
1602 if(peer->Send_ShakeInfo() < 0){
1603 + if(arg_verbose) fprintf(stderr, "close: Sending handshake\n");
1604 peer->CloseConnection();
1607 peer->SetStatus(P_HANDSHAKE);
1609 + }else if(FD_ISSET(sk,rfdp)){
1611 + peer->CloseConnection();
1614 if(FD_ISSET(sk,rfdp)){
1615 @@ -493,18 +609,29 @@
1618 if(peer->GetStatus() == P_HANDSHAKE){
1619 - if( peer->HandShake() < 0 ) peer->CloseConnection();
1621 - if( peer->RecvModule() < 0 ) peer->CloseConnection();
1622 + if( peer->HandShake() < 0 ) {
1623 + if(arg_verbose) fprintf(stderr, "close: bad handshake\n");
1624 + peer->CloseConnection();
1626 + } // fixed client stall
1627 + if(peer->GetStatus() == P_SUCCESS){
1628 + if( peer->RecvModule() < 0 ) {
1629 + if(arg_verbose) fprintf(stderr, "close: receive\n");
1630 + peer->CloseConnection();
1633 - }else if(PEER_IS_SUCCESS(peer) && FD_ISSET(sk,wfdp)){
1635 + if(PEER_IS_SUCCESS(peer) && FD_ISSET(sk,wfdp)){
1638 for(p2 = m_head; p2; p2=p2->next) p2->click = 0;
1642 - if( peer->SendModule() < 0 ) peer->CloseConnection();
1643 + if( peer->SendModule() < 0 ) {
1644 + if(arg_verbose) fprintf(stderr, "close: send\n");
1645 + peer->CloseConnection();
1650 @@ -514,7 +641,11 @@
1652 PEERNODE *p = m_head;
1653 for( ; p; p = p->next)
1654 - if(p->peer->bitfield.IsFull()) p->peer->CloseConnection();
1655 +// if(p->peer->bitfield.IsFull()) p->peer->CloseConnection();
1656 + if(p->peer->bitfield.IsFull()) {
1657 + if(arg_verbose) fprintf(stderr, "close: seed<->seed\n");
1658 + p->peer->CloseConnection();
1662 void PeerList::UnChokeCheck(btPeer* peer, btPeer *peer_array[])
1663 @@ -523,8 +654,15 @@
1665 btPeer *loster = (btPeer*) 0;
1666 int f_seed = BTCONTENT.pBF->IsFull();
1669 + if (m_opt_timestamp) no_opt = 1;
1671 - for( cancel_idx = i = 0; i < MAX_UNCHOKE; i++ ){
1672 +// Find my 3 or 4 fastest peers.
1673 +// The MAX_UNCHOKE+1 (4th) slot is for the optimistic unchoke when it happens.
1675 + // Find a slot for the candidate--the slowest peer, or an available slot.
1676 + for( cancel_idx = i = 0; i < MAX_UNCHOKE+no_opt; i++ ){
1677 if((btPeer*) 0 == peer_array[i] || PEER_IS_FAILED(peer_array[i]) ){ // ÓпÕλ
1680 @@ -537,7 +675,13 @@
1683 // compare download rate.
1684 - if(peer_array[cancel_idx]->RateDL() > peer_array[i]->RateDL())
1685 +// if(peer_array[cancel_idx]->RateDL() > peer_array[i]->RateDL())
1686 + if( peer_array[cancel_idx]->RateDL() > peer_array[i]->RateDL()
1687 + //if equal, reciprocate to the peer we've sent less to, proportionally
1688 + ||(peer_array[cancel_idx]->RateDL() == peer_array[i]->RateDL()
1689 + && peer_array[cancel_idx]->TotalUL()
1690 + / (peer_array[cancel_idx]->TotalDL()+.001)
1691 + < peer_array[i]->TotalUL() / (peer_array[i]->TotalDL()+.001)) )
1695 @@ -551,7 +695,13 @@
1699 - if(peer->RateDL() > peer_array[cancel_idx]->RateDL()){
1700 +// if(peer->RateDL() > peer_array[cancel_idx]->RateDL()){
1701 + if( peer->RateDL() > peer_array[cancel_idx]->RateDL()
1702 + // If equal, reciprocate to the peer we've sent less to, proportionally
1703 + ||(peer_array[cancel_idx]->RateDL() == peer->RateDL()
1704 + && peer_array[cancel_idx]->TotalUL()
1705 + / (peer_array[cancel_idx]->TotalDL()+.001)
1706 + > peer->TotalUL() / (peer->TotalDL()+.001)) ){
1707 loster = peer_array[cancel_idx];
1708 peer_array[cancel_idx] = peer;
1710 @@ -559,15 +709,56 @@
1714 - if((btPeer*) 0 == peer_array[MAX_UNCHOKE] || PEER_IS_FAILED(peer_array[MAX_UNCHOKE]) )
1716 + if(loster->SetLocal(M_CHOKE) < 0) loster->CloseConnection();
1719 + // The last slot is for the optimistic unchoke.
1720 + // Bump the loser into it if he's been waiting longer than the occupant.
1721 + if((btPeer*) 0 == peer_array[MAX_UNCHOKE] || PEER_IS_FAILED(peer_array[MAX_UNCHOKE]))
1722 peer_array[MAX_UNCHOKE] = loster;
1724 - if(loster->GetLastUnchokeTime() < peer_array[MAX_UNCHOKE]->GetLastUnchokeTime())
1725 - peer_array[MAX_UNCHOKE] = loster;
1727 - if(loster->SetLocal(M_CHOKE) < 0) loster->CloseConnection();
1729 +// if(loster->GetLastUnchokeTime() < peer_array[MAX_UNCHOKE]->GetLastUnchokeTime()) {
1730 + // if loser is empty and current is not, loser gets 75% chance.
1731 + if( loster->bitfield.IsEmpty() && !peer_array[MAX_UNCHOKE]->bitfield.IsEmpty()
1732 + && random()&03 ) {
1733 + btPeer* tmp = peer_array[MAX_UNCHOKE];
1734 + peer_array[MAX_UNCHOKE] = loster;
1736 + } else // if loser waited longer:
1737 + if(loster->GetLastUnchokeTime() < peer_array[MAX_UNCHOKE]->GetLastUnchokeTime()) {
1738 + // if current is empty and loser is not, loser gets 25% chance;
1739 + // else loser wins.
1740 + // transformed to: if loser is empty or current isn't, or 25% chance,
1741 + // then loser wins.
1742 + if( !peer_array[MAX_UNCHOKE]->bitfield.IsEmpty() || loster->bitfield.IsEmpty()
1743 + || !random()&03 ) {
1744 + btPeer* tmp = peer_array[MAX_UNCHOKE];
1745 + peer_array[MAX_UNCHOKE] = loster;
1749 + if(loster->SetLocal(M_CHOKE) < 0) loster->CloseConnection();
1751 }else //else if((btPeer*) 0 != peer_array[cancel_idx].....
1752 peer_array[cancel_idx] = peer;
1755 +// When we change what we're going after, we need to evaluate & set our
1756 +// interest with each peer appropriately.
1757 +void PeerList::CheckInterest()
1759 + PEERNODE *p = m_head;
1760 + for( ; p; p = p->next) {
1761 + // Don't shortcut by checking Is_Local_Interested(), as we need to let
1762 + // SetLocal() reset the m_standby flag.
1763 + if( p->peer->Need_Remote_Data() ) {
1764 + if( p->peer->SetLocal(M_INTERESTED) < 0 )
1765 + p->peer->CloseConnection();
1767 + if( p->peer->SetLocal(M_NOT_INTERESTED) < 0 )
1768 + p->peer->CloseConnection();
1773 diff -u ctorrent-1.3.4.orig/peerlist.h ctorrent-1.3.4/peerlist.h
1774 --- ctorrent-1.3.4.orig/peerlist.h 2004-09-09 01:10:51.000000000 +0200
1775 +++ ctorrent-1.3.4/peerlist.h 2005-08-11 23:45:29.434692920 +0200
1777 SOCKET m_listen_sock;
1779 size_t m_peers_count;
1780 - time_t m_unchoke_check_timestamp, m_keepalive_check_timestamp, m_last_progress_timestamp;
1781 + size_t m_seeds_count;
1782 + time_t m_unchoke_check_timestamp, m_keepalive_check_timestamp, m_last_progress_timestamp, m_opt_timestamp;
1784 unsigned char m_live_idx:2;
1785 unsigned char m_reserved:6;
1788 void Tell_World_I_Have(size_t idx);
1789 btPeer* Who_Can_Abandon(btPeer *proposer);
1790 + btPeer* Who_Can_Duplicate(btPeer *proposer, size_t idx);
1791 + void CancelSlice(size_t idx, size_t off, size_t len);
1792 void CheckBitField(BitField &bf);
1793 int AlreadyRequested(size_t idx);
1794 size_t Pieces_I_Can_Get();
1795 + void CheckInterest();
1798 extern PeerList WORLD;
1799 diff -u ctorrent-1.3.4.orig/rate.cpp ctorrent-1.3.4/rate.cpp
1800 --- ctorrent-1.3.4.orig/rate.cpp 2004-09-09 01:10:51.000000000 +0200
1801 +++ ctorrent-1.3.4/rate.cpp 2005-08-11 23:45:29.434692920 +0200
1805 +#define RATE_INTERVAL 20
1807 void Rate::StartTimer()
1809 if( !m_last_timestamp ) time(&m_last_timestamp);
1812 void Rate::StopTimer()
1814 - if( !m_last_timestamp ){
1815 + if( m_last_timestamp ){
1816 m_total_timeused += (time((time_t*) 0) - m_last_timestamp);
1817 m_last_timestamp = 0;
1821 void Rate::CountAdd(size_t nbytes)
1823 + time_t now = time((time_t*) 0);
1825 m_count_bytes += nbytes;
1827 + // save bandwidth history data
1828 + for (int i=0; i <= n_samples; i++)
1830 + if (i < MAX_SAMPLES)
1832 + if (now == m_timestamp_sample[i]) {
1833 + m_bytes_sample[i] += nbytes;
1836 + else if (now - RATE_INTERVAL > m_timestamp_sample[i]) {
1837 + m_timestamp_sample[i] = now;
1838 + m_bytes_sample[i] = nbytes;
1839 + if (n_samples < MAX_SAMPLES) n_samples++;
1846 void Rate::operator=(const Rate &ra)
1849 size_t Rate::RateMeasure() const
1851 - time_t timeused = m_total_timeused;
1852 - if( m_last_timestamp ) timeused += (time((time_t*) 0) - m_last_timestamp);
1853 + // calculate rate based on bandwidth history data
1854 + time_t timestamp = time((time_t*) 0);
1855 + u_int64_t countbytes = 0;
1856 + time_t timeused = 0;
1858 + if( !m_last_timestamp ) return 0; // no current rate
1860 + timeused = (TimeUsed(×tamp) < RATE_INTERVAL) ?
1861 + TimeUsed(×tamp) : RATE_INTERVAL;
1862 if( timeused < 1 ) timeused = 1;
1863 - return (size_t)(m_count_bytes / timeused);
1865 + for (int i=0; i<n_samples; i++)
1867 + if (timestamp - m_timestamp_sample[i] <= timeused)
1868 + countbytes += m_bytes_sample[i];
1870 + return (size_t)(countbytes / timeused);
1873 size_t Rate::RateMeasure(const Rate &ra_to) const
1876 time_t timeused = time((time_t*) 0) - m_last_timestamp;
1877 if( timeused < 1 ) timeused = 1;
1878 - return (size_t)((ra_to.m_count_bytes - m_count_bytes) / timeused);
1879 + tmp = (ra_to.m_count_bytes - ra_to.m_recent_base)
1880 + - (m_count_bytes - m_recent_base);
1881 + return (size_t)( (tmp>0) ? (tmp/timeused) : 0 );
1884 time_t Rate::TimeUsed(const time_t *pnow) const
1885 diff -u ctorrent-1.3.4.orig/rate.h ctorrent-1.3.4/rate.h
1886 --- ctorrent-1.3.4.orig/rate.h 2004-09-09 01:10:51.000000000 +0200
1887 +++ ctorrent-1.3.4/rate.h 2005-08-11 23:45:29.434692920 +0200
1892 +#define MAX_SAMPLES 20
1896 time_t m_last_timestamp;
1897 time_t m_total_timeused;
1898 u_int64_t m_count_bytes;
1899 + u_int64_t m_recent_base;
1901 + // bandwidth history data
1903 + time_t m_timestamp_sample[MAX_SAMPLES];
1904 + u_int64_t m_bytes_sample[MAX_SAMPLES];
1907 - Rate(){ m_last_timestamp = m_total_timeused = (time_t)0; m_count_bytes = 0; }
1908 - void Reset(){ m_last_timestamp = m_total_timeused = (time_t)0; m_count_bytes = 0;}
1909 + Rate(){ m_last_timestamp = m_total_timeused = (time_t)0;
1910 + m_recent_base = m_count_bytes = 0;
1911 + n_samples=0; for(int i=0;i<MAX_SAMPLES;i++) m_timestamp_sample[i]=0;
1913 + void Reset(){ m_last_timestamp = m_total_timeused = (time_t)0;
1914 + m_recent_base = m_count_bytes;
1915 + n_samples = 0; for(int i=0;i<MAX_SAMPLES;i++) m_timestamp_sample[i]=0;
1919 void CountAdd(size_t nbytes);
1920 diff -u ctorrent-1.3.4.orig/sigint.cpp ctorrent-1.3.4/sigint.cpp
1921 --- ctorrent-1.3.4.orig/sigint.cpp 2004-09-09 01:10:51.000000000 +0200
1922 +++ ctorrent-1.3.4/sigint.cpp 2005-08-11 23:45:29.434692920 +0200
1926 #include "btcontent.h"
1927 +#include "tracker.h"
1928 #include "peerlist.h"
1929 #include "btconfig.h"
1930 +#include "sigint.h"
1932 -void sigint_catch(int sig_no)
1933 +void sig_catch(int sig_no)
1935 - if(SIGINT == sig_no){
1936 + if(SIGINT == sig_no || SIGTERM == sig_no){
1937 + Tracker.SetStoped();
1938 + signal(sig_no,sig_catch2);
1942 +static void sig_catch2(int sig_no)
1944 + if(SIGINT == sig_no || SIGTERM == sig_no){
1945 if( cfg_cache_size ) BTCONTENT.FlushCache();
1946 if( arg_bitfield_file ) BTCONTENT.pBF->WriteToFile(arg_bitfield_file);
1948 - signal(SIGINT,SIG_DFL);
1950 + signal(sig_no,SIG_DFL);
1955 diff -u ctorrent-1.3.4.orig/sigint.h ctorrent-1.3.4/sigint.h
1956 --- ctorrent-1.3.4.orig/sigint.h 2004-09-09 01:10:51.000000000 +0200
1957 +++ ctorrent-1.3.4/sigint.h 2005-08-11 23:45:29.435692768 +0200
1962 -void sigint_catch(int sig_no);
1963 +void sig_catch(int sig_no);
1964 +static void sig_catch2(int sig_no);
1968 diff -u ctorrent-1.3.4.orig/tracker.cpp ctorrent-1.3.4/tracker.cpp
1969 --- ctorrent-1.3.4.orig/tracker.cpp 2004-09-09 01:10:51.000000000 +0200
1970 +++ ctorrent-1.3.4/tracker.cpp 2005-08-11 23:45:29.435692768 +0200
1972 m_sock = INVALID_SOCKET;
1975 - m_f_started = m_f_stoped = m_f_pause = 0;
1976 + m_f_started = m_f_stoped = m_f_pause = m_f_completed = 0;
1979 m_connect_refuse_click = 0;
1980 m_last_timestamp = (time_t) 0;
1984 btTracker::~btTracker()
1987 m_reponse_buffer.Reset();
1988 time(&m_last_timestamp);
1989 - m_status = T_FREE;
1990 + if (m_f_stoped) m_status = T_FINISHED;
1991 + else m_status = T_FREE;
1994 int btTracker:: _IPsin(char *h, int p, struct sockaddr_in *psin)
1995 @@ -111,6 +113,13 @@
1997 if(m_interval != (time_t)i) m_interval = (time_t)i;
1999 + if(decode_query(buf,bufsiz,"complete",(const char**) 0,&i,QUERY_INT)) {
2000 + m_peers_count = i;
2002 + if(decode_query(buf,bufsiz,"incomplete",(const char**) 0,&i,QUERY_INT)) {
2003 + m_peers_count += i;
2006 pos = decode_query(buf,bufsiz,"peers",(const char**) 0,(size_t *) 0,QUERY_POS);
2009 @@ -161,7 +170,10 @@
2013 - if( !cnt ) fprintf(stderr,"warn, peers list received from tracker is empty.\n");
2015 + fprintf(stderr, "\nnew peers=%u; next check in %u sec\n", cnt, m_interval);
2016 +// moved to CheckResponse--this function isn't called if no peer data.
2017 +// if( !cnt ) fprintf(stderr,"warn, peers list received from tracker is empty.\n");
2021 @@ -230,10 +242,14 @@
2025 - if ( !pdata ) return 0;
2027 + fprintf(stderr,"warn, peers list received from tracker is empty.\n");
2031 if( !m_f_started ) m_f_started = 1;
2032 m_connect_refuse_click = 0;
2035 return _UpdatePeerList(pdata,dlen);
2037 @@ -329,30 +345,34 @@
2038 // fprintf(stdout,"Old Set Self:");
2039 // fprintf(stdout,"%s\n", inet_ntoa(Self.m_sin.sin_addr));
2041 - if( m_f_stoped ) /* stopped */
2042 - event = str_event[1];
2043 - else if( BTCONTENT.pBF->IsFull()) /* download complete */
2044 - event = str_event[2];
2045 - else if( m_f_started ) /* interval */
2046 - event = (char*) 0;
2049 + event = str_event[1]; /* stopped */
2050 + else if( m_f_started == 0 ) {
2051 + if( BTCONTENT.pBF->IsFull() ) m_f_completed = 1;
2052 event = str_event[0]; /* started */
2053 + } else if( BTCONTENT.pBF->IsFull() && !m_f_completed){
2054 + event = str_event[2]; /* download complete */
2055 + m_f_completed = 1; /* only send download complete once */
2057 + event = (char*) 0; /* interval */
2060 if(MAXPATHLEN < snprintf(REQ_BUFFER,MAXPATHLEN,REQ_URL_P2_FMT,
2062 - (size_t)Self.TotalUL(),
2063 - (size_t)Self.TotalDL(),
2064 - (size_t)BTCONTENT.GetLeftBytes(),
2068 + BTCONTENT.GetLeftBytes(),
2074 if(MAXPATHLEN < snprintf(REQ_BUFFER,MAXPATHLEN,REQ_URL_P3_FMT,
2076 - (size_t)Self.TotalUL(),
2077 - (size_t)Self.TotalDL(),
2078 - (size_t)BTCONTENT.GetLeftBytes()
2081 + BTCONTENT.GetLeftBytes(),
2086 @@ -380,8 +400,12 @@
2088 /* tracker communication */
2089 if( T_FREE == m_status ){
2090 - if((*pnow - m_last_timestamp >= m_interval) &&
2091 - (cfg_min_peers > WORLD.TotalPeers())){
2092 +// if(*pnow - m_last_timestamp >= m_interval){
2093 + if(*pnow - m_last_timestamp >= m_interval ||
2094 + // Connect to tracker early if we run out of peers.
2095 + (!WORLD.TotalPeers() && m_prevpeers &&
2096 + *pnow - m_last_timestamp >= 15) ){
2097 + m_prevpeers = WORLD.TotalPeers();
2099 if(Connect() < 0){ Reset(15); return -1; }
2102 if( m_status == T_CONNECTING ){
2103 FD_SET(m_sock, rfdp);
2104 FD_SET(m_sock, wfdp);
2106 + }else if (INVALID_SOCKET != m_sock){
2107 FD_SET(m_sock, rfdp);
2111 if( SendRequest() == 0 ) m_status = T_READY;
2112 else { Reset(15); return -1; }
2114 - }else if(FD_ISSET(m_sock, rfdp) ){
2115 + }else if(INVALID_SOCKET != m_sock && FD_ISSET(m_sock, rfdp) ){
2117 FD_CLR(m_sock,rfdp);
2119 diff -u ctorrent-1.3.4.orig/tracker.h ctorrent-1.3.4/tracker.h
2120 --- ctorrent-1.3.4.orig/tracker.h 2004-09-09 01:10:51.000000000 +0200
2121 +++ ctorrent-1.3.4/tracker.h 2005-08-11 23:45:29.436692616 +0200
2124 #define T_CONNECTING 1
2126 +#define T_FINISHED 3
2131 unsigned char m_status:2;
2132 unsigned char m_f_started:1;
2133 unsigned char m_f_stoped:1;
2134 + unsigned char m_f_completed:1;
2136 unsigned char m_f_pause:1;
2137 - unsigned char m_f_reserved:3;
2138 + unsigned char m_f_reserved:2;
2141 time_t m_interval; // ÓëTrackerͨÐŵÄʱ¼ä¼ä¸ô
2142 time_t m_last_timestamp; // ×îºóÒ»´Î³É¹¦ÓëTrackerͨÐŵÄʱ¼ä
2143 size_t m_connect_refuse_click;
2145 + size_t m_ok_click; // tracker ok response counter
2146 + size_t m_peers_count; // total number of peers
2147 + size_t m_prevpeers; // number of peers previously seen
2150 BufIo m_reponse_buffer;
2153 void SetPause() { m_f_pause = 1; }
2154 void ClearPause() { m_f_pause = 0; }
2156 + void SetStoped() { Reset(15); m_f_stoped = 1; m_last_timestamp -= 15;}
2162 int SocketReady(fd_set *rfdp, fd_set *wfdp, int *nfds);
2164 size_t GetRefuseClick() const { return m_connect_refuse_click; }
2165 + size_t GetOkClick() const { return m_ok_click; }
2166 + size_t GetPeersCount() const { return m_peers_count; }
2169 extern btTracker Tracker;