ctcs.cpp
来自「最经典的bittorrent协议的实现的源码」· C++ 代码 · 共 837 行 · 第 1/2 页
CPP
837 行
}int Ctcs::Set_Config(char *msgbuf){ if( m_protocol >= 3 ){ char *name, *valstr; name = strtok(strchr(msgbuf, ' '), " "); for( valstr=name+strlen(name)+1; *valstr==' '; valstr++ ); if( 0==strcmp(name, "verbose") ){ int arg = atoi(valstr); if( arg_verbose && !arg ) CONSOLE.Debug("Verbose output off"); arg_verbose = arg; }else if( 0==strcmp(name, "seed_time") ){ time_t arg = (time_t)strtoul(valstr, NULL, 10); arg += BTCONTENT.GetSeedTime() ? ((now - BTCONTENT.GetSeedTime()) / 3600) : 0; if( arg > 0 || 0==BTCONTENT.GetSeedTime() || cfg_seed_ratio > (double) Self.TotalUL() / (Self.TotalDL() ? Self.TotalDL() : BTCONTENT.GetTotalFilesLength()) ) cfg_seed_hours = arg; }else if( 0==strcmp(name, "seed_ratio") ){ double arg = atof(valstr); if( 0==BTCONTENT.GetSeedTime() || cfg_seed_hours > (now - BTCONTENT.GetSeedTime()) / 3600 || arg > (double) Self.TotalUL() / (Self.TotalDL() ? Self.TotalDL() : BTCONTENT.GetTotalFilesLength()) ) cfg_seed_ratio = arg; }else if( 0==strcmp(name, "max_peers") ){ cfg_max_peers = atoi(valstr); }else if( 0==strcmp(name, "min_peers") ){ cfg_min_peers = atoi(valstr); }else if( 0==strcmp(name, "file_list") ){ if( arg_file_to_download ) delete []arg_file_to_download; if( 0==strlen(valstr) ) arg_file_to_download = (char *)0; else{ arg_file_to_download = new char[strlen(valstr) + 1]; if( !arg_file_to_download ) CONSOLE.Warning(1, "error, failed to allocate memory for option"); else strcpy(arg_file_to_download, valstr); } BTCONTENT.SetFilter(); }else if( 0==strcmp(name, "cache") ){ cfg_cache_size = atoi(valstr); BTCONTENT.CacheConfigure(); }else if( 0==strcmp(name, "pause") ){ if( atoi(valstr) ){ if( !WORLD.IsPaused() ) WORLD.Pause(); }else if( WORLD.IsPaused() ) WORLD.Resume(); }else if( 0==strcmp(name, "user_exit") ){ if( arg_completion_exit ) delete []arg_completion_exit; arg_completion_exit = new char[strlen(valstr) + 1]; if( !arg_completion_exit ) CONSOLE.Warning(1, "error, failed to allocate memory for option"); else strcpy(arg_completion_exit, valstr); }else if( 0==strcmp(name, "out_normal") ){ CONSOLE.ChangeChannel(O_NORMAL, valstr); }else if( 0==strcmp(name, "out_interact") ){ CONSOLE.ChangeChannel(O_INTERACT, valstr); }else if( 0==strcmp(name, "out_error") ){ CONSOLE.ChangeChannel(O_WARNING, valstr); }else if( 0==strcmp(name, "out_debug") ){ CONSOLE.ChangeChannel(O_DEBUG, valstr); }else if( 0==strcmp(name, "input") ){ CONSOLE.ChangeChannel(O_INPUT, valstr); }else CONSOLE.Warning(2, "Unknown config option %s from CTCS", name); }else{ // m_protocol <= 2 if(msgbuf[9] != '.'){ int arg = atoi(msgbuf+9); if( arg_verbose && !arg ) CONSOLE.Debug("Verbose output off"); arg_verbose = arg; } if(msgbuf[11] != '.') cfg_seed_hours = atoi(msgbuf+11); msgbuf = strchr(msgbuf+11, ' ') + 1; if(msgbuf[0] != '.') cfg_seed_ratio = atof(msgbuf); msgbuf = strchr(msgbuf, ' ') + 1; if(msgbuf[0] != '.') cfg_max_peers = atoi(msgbuf); msgbuf = strchr(msgbuf, ' ') + 1; if(msgbuf[0] != '.') cfg_min_peers = atoi(msgbuf); msgbuf = strchr(msgbuf, ' ') + 1; if(msgbuf[0] != '.'){ char *p = strchr(msgbuf, ' '); if( arg_file_to_download ) delete []arg_file_to_download; arg_file_to_download = new char[p - msgbuf + 2 + 1]; if( !arg_file_to_download ) CONSOLE.Warning(1, "error, failed to allocate memory for option"); else{ strncpy(arg_file_to_download, msgbuf, p - msgbuf); arg_file_to_download[p - msgbuf] = '\0'; strcat(arg_file_to_download, ",*"); // mock old behavior } BTCONTENT.SetFilter(); } if( m_protocol >= 2 ){ msgbuf = strchr(msgbuf, ' ') + 1; if(msgbuf[0] != '.'){ cfg_cache_size = atoi(msgbuf); BTCONTENT.CacheConfigure(); } } if( m_protocol == 1 ){ msgbuf = strchr(msgbuf, ' ') + 1; // old cfg_exit_zero_peers option } msgbuf = strchr(msgbuf, ' ') + 1; if(msgbuf[0] != '.'){ if(atoi(msgbuf)){ if( !WORLD.IsPaused() ) WORLD.Pause(); }else if( WORLD.IsPaused() ) WORLD.Resume(); } } return 0;}int Ctcs::Send_Detail(){ char message[CTCS_BUFSIZE]; int r=0, priority, current=0; size_t n=0; BTFILE *file=0; BitField tmpBitField, fileFilter, availbf, tmpavail, allFilter, tmpFilter, *pfilter; snprintf( message, CTCS_BUFSIZE, "CTDETAIL %lld %d %ld %ld", BTCONTENT.GetTotalFilesLength(), (int)(BTCONTENT.GetPieceLength()), (long)now, (long)(BTCONTENT.GetSeedTime()) ); r = SendMessage(message); if(r==0) r = SendMessage((m_protocol >= 3) ? "CTFILESTART" : "CTFILES"); if( m_protocol >= 3 ){ // determine current download priority pfilter = (BitField *)0; while( pfilter != BTCONTENT.GetFilter() ){ current++; pfilter = BTCONTENT.GetNextFilter(pfilter); } } WORLD.Pieces_I_Can_Get(&availbf); while( r==0 && ++n <= BTCONTENT.GetNFiles() ){ tmpBitField = *BTCONTENT.pBF; BTCONTENT.SetTmpFilter(n, &fileFilter); tmpBitField.Except(fileFilter); // the pieces of this file that I have tmpavail = availbf; tmpavail.Except(fileFilter); // the available pieces of this file if( m_protocol >= 3 ){ priority = 0; if( BTCONTENT.GetFilter() ){ fileFilter.Invert(); allFilter.SetAll(); pfilter = (BitField *)0; while( pfilter = BTCONTENT.GetNextFilter(pfilter) ){ priority++; allFilter.And(*pfilter); // cumulation of filters tmpFilter = allFilter; tmpFilter.Invert(); // what's included by the filters... tmpFilter.And(fileFilter); // ...that's also in this file if( tmpFilter.Count() >= fileFilter.Count() ) break; } if( !pfilter ) priority = 0; } snprintf( message, CTCS_BUFSIZE, "CTFILE %d %d %d %d %d %d %llu %s", (int)n, priority, current, (int)(BTCONTENT.GetFilePieces(n)), (int)(tmpBitField.Count()), (int)(tmpavail.Count()), (unsigned long long)(BTCONTENT.GetFileSize(n)), BTCONTENT.GetFileName(n) ); } else if( m_protocol == 2 ) snprintf( message, CTCS_BUFSIZE, "CTFILE %d %d %d %d %llu %s", (int)n, (int)(BTCONTENT.GetFilePieces(n)), (int)(tmpBitField.Count()), (int)(tmpavail.Count()), (unsigned long long)(BTCONTENT.GetFileSize(n)), BTCONTENT.GetFileName(n) ); else // m_protocol == 1 snprintf( message, CTCS_BUFSIZE, "CTFILE %d %d %d %llu %s", (int)n, (int)(BTCONTENT.GetFilePieces(n)), (int)(tmpBitField.Count()), (unsigned long long)(BTCONTENT.GetFileSize(n)), BTCONTENT.GetFileName(n) ); r = SendMessage(message); } if(r==0) r = SendMessage((m_protocol >= 3) ? "CTFILESDONE" : "CTFDONE"); return r;}int Ctcs::Send_Peers(){ btPeer *peer=0; char message[CTCS_BUFSIZE]; char txtid[PEER_ID_LEN*2+3]; struct sockaddr_in psin; int r=0; r=SendMessage((m_protocol >= 3) ? "CTPEERSTART" : "CTPEERS"); while( r==0 && (peer = WORLD.GetNextPeer(peer)) ){ TextPeerID(peer->id, txtid); peer->GetAddress(&psin); snprintf(message, CTCS_BUFSIZE, "CTPEER %s %s %c%c%c%c %d %d %llu %llu %d", txtid, inet_ntoa(psin.sin_addr), peer->Is_Remote_UnChoked() ? 'U' : 'C', peer->Is_Local_Interested() ? 'i' : 'n', peer->Is_Local_UnChoked() ? 'U' : 'C', peer->Is_Remote_Interested() ? 'i' : 'n', (int)(peer->RateDL()), (int)(peer->RateUL()), (unsigned long long)(peer->TotalDL()), (unsigned long long)(peer->TotalUL()), (int)(peer->bitfield.Count()) ); r = SendMessage(message); } if(r==0) r = SendMessage((m_protocol >= 3) ? "CTPEERSDONE" : "CTPDONE"); return r;}int Ctcs::Send_Info(int sev, const char *info){ char message[CTCS_BUFSIZE]; snprintf(message, CTCS_BUFSIZE, "CTINFO %d %s", sev, info); return SendMessage(message);}int Ctcs::Initial(){ char *s; strncpy(m_host, arg_ctcs, MAXHOSTNAMELEN-1); m_host[MAXHOSTNAMELEN-1] = '\0'; if( s = strchr(m_host, ':') ) *s='\0'; m_port = atoi(s=(strchr(arg_ctcs, ':')+1)); if(strchr(s, ':')){ CONSOLE.Input("Enter CTCS password: ", m_pass, CTCS_PASS_SIZE); } else *m_pass = '\0'; return 0;}int Ctcs::Connect(){ ssize_t r; m_last_timestamp = now; if(_s2sin(m_host,m_port,&m_sin) < 0) { CONSOLE.Warning(2, "warn, get CTCS ip address failed."); return -1; } m_sock = socket(AF_INET,SOCK_STREAM,0); if(INVALID_SOCKET == m_sock) return -1; if(setfd_nonblock(m_sock) < 0) {CLOSE_SOCKET(m_sock); return -1; } r = connect_nonb(m_sock,(struct sockaddr*)&m_sin); if( r == -1 ){ CLOSE_SOCKET(m_sock); return -1;} else if( r == -2 ) m_status = T_CONNECTING; else{ m_status = T_READY; if( Send_Protocol() != 0 && errno != EINPROGRESS ){ CONSOLE.Warning(2, "warn, send protocol to CTCS failed: %s", strerror(errno)); return -1; } if( Send_Auth() != 0 && errno != EINPROGRESS ) { CONSOLE.Warning(2, "warn, send password to CTCS failed: %s", strerror(errno)); return -1; } if( Send_Torrent(BTCONTENT.GetPeerId(), arg_metainfo_file) != 0 && errno != EINPROGRESS ){ CONSOLE.Warning(2, "warn, send torrent to CTCS failed: %s", strerror(errno)); return -1; } } return 0;}int Ctcs::IntervalCheck(fd_set *rfdp, fd_set *wfdp){ if( T_FREE == m_status ){ if( INVALID_SOCKET != m_sock ){ FD_CLR(m_sock, rfdp); FD_CLR(m_sock, wfdp); } if( now - m_last_timestamp >= m_interval ){ if(Connect() < 0){ Reset(15); return -1; } FD_SET(m_sock, rfdp); if( m_status == T_CONNECTING ) FD_SET(m_sock, wfdp); }else if( now < m_last_timestamp ) m_last_timestamp = now; }else{ if( m_status == T_CONNECTING ){ FD_SET(m_sock, rfdp); FD_SET(m_sock, wfdp); }else if( INVALID_SOCKET != m_sock ){ if( now > m_statustime ){ Report_Status( WORLD.GetSeedsCount(), WORLD.GetPeersCount() - WORLD.GetSeedsCount() - WORLD.GetConnCount(), BTCONTENT.pBF->Count(), BTCONTENT.GetNPieces(), Self.RateDL(), Self.RateUL(), Self.TotalDL(), Self.TotalUL(), cfg_max_bandwidth_down, cfg_max_bandwidth_up, BTCONTENT.CacheUsed()/1024 ); m_statustime = now; } FD_SET(m_sock, rfdp); if( out_buffer.Count() ) FD_SET(m_sock, wfdp); } } return m_sock;}int Ctcs::SocketReady(fd_set *rfdp, fd_set *wfdp, int *nfds, fd_set *rfdnextp, fd_set *wfdnextp){ if( T_FREE == m_status ) return 0; if( T_CONNECTING == m_status && FD_ISSET(m_sock,wfdp) ){ int error = 0; socklen_t n = sizeof(error); (*nfds)--; FD_CLR(m_sock, wfdnextp); if( FD_ISSET(m_sock, rfdp) ){ (*nfds)--; FD_CLR(m_sock, rfdnextp); } if(getsockopt(m_sock, SOL_SOCKET,SO_ERROR,&error,&n) < 0) error = errno; if( error != 0 ){ if( ECONNREFUSED != error ) CONSOLE.Warning(2, "warn, connect to CTCS failed: %s", strerror(error)); Reset(15); return -1; }else{ m_status = T_READY; if( Send_Protocol() != 0 && errno != EINPROGRESS ){ CONSOLE.Warning(2, "warn, send protocol to CTCS failed: %s", strerror(errno)); return -1; } if( Send_Auth() != 0 && errno != EINPROGRESS ) { CONSOLE.Warning(2, "warn, send password to CTCS failed: %s", strerror(errno)); return -1; } if( Send_Torrent(BTCONTENT.GetPeerId(), arg_metainfo_file) == 0 && errno != EINPROGRESS ){ CONSOLE.Warning(2, "warn, send torrent to CTCS failed: %s", strerror(errno)); return -1; } } }else if( T_CONNECTING == m_status && FD_ISSET(m_sock,rfdp) ){ int error = 0; socklen_t n = sizeof(error); (*nfds)--; FD_CLR(m_sock, rfdnextp); if(getsockopt(m_sock, SOL_SOCKET,SO_ERROR,&error,&n) < 0) error = errno; CONSOLE.Warning(2, "warn, connect to CTCS failed: %s", strerror(error)); Reset(15); return -1; }else if( INVALID_SOCKET != m_sock ){ if( FD_ISSET(m_sock, rfdp) ){ (*nfds)--; FD_CLR(m_sock,rfdnextp); SOCKET tmp_sock = m_sock; int r = CheckMessage(); if( INVALID_SOCKET == m_sock ){ if( FD_ISSET(tmp_sock, wfdp) ){ (*nfds)--; FD_CLR(tmp_sock,wfdnextp); } return r; } } if( FD_ISSET(m_sock, wfdp) ){ (*nfds)--; FD_CLR(m_sock,wfdnextp); if( out_buffer.Count() && out_buffer.FlushOut(m_sock) < 0 ){ Reset(5); return -1; } } }else{ // failsafe Reset(5); return -1; } return 0;}void Ctcs::RestartTracker(){ Tracker.SetStoped(); // finish the tracker // Now we need to wait until the tracker updates (T_FINISHED == m_status), // then Tracker.Restart(). Tracker.SetRestart();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?