📄 ctcs.cpp
字号:
} strcpy(msgbuf, origmsg); if( m_protocol >= 3 ){ char *name, *valstr; if( !(name = strtok(strchr(msgbuf, ' '), " ")) || strlen(name) >= strlen(origmsg) - (name - msgbuf) ) goto err; valstr = name + strlen(name); for( ++valstr; *valstr==' '; valstr++ ); if( 0==strcmp(name, "verbose") ){ int arg = atoi(valstr); if( arg < 0 ) goto err; if( arg_verbose && !arg ) CONSOLE.Debug("Verbose output off"); arg_verbose = arg; }else if( 0==strcmp(name, "seed_time") ){ double value = strtod(valstr, NULL); if( value < 0 ) goto err; time_t arg = (time_t)value + ((value - (int)value) ? 1 : 0); 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( arg < 0 ) goto err; 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") ){ int arg = atoi(valstr); if( arg > 1000 || arg < 20 ) goto err; cfg_max_peers = arg; }else if( 0==strcmp(name, "min_peers") ){ int arg = atoi(valstr); if( arg > 1000 || arg < 1 ) goto err; cfg_min_peers = arg; }else if( 0==strcmp(name, "file_list") ){ if( !BTCONTENT.IsFull() ){ 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") ){ int arg = atoi(valstr); if( arg < 0 ) goto err; cfg_cache_size = arg; BTCONTENT.CacheConfigure(); }else if( 0==strcmp(name, "pause") ){ int arg = atoi(valstr); if( arg < 0 ) goto err; if( arg ){ if( !WORLD.IsPaused() ) WORLD.Pause(); }else if( WORLD.IsPaused() ) WORLD.Resume(); }else if( 0==strcmp(name, "user_exit") ){ if( !BTCONTENT.IsFull() ){ 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 if( 0==strcmp(name, "ctcs_server") ){ if( !strchr(valstr, ':') || *valstr == ':' || atoi(strchr(valstr, ':') + 1) <= 0 ) goto err; char *arg = new char[strlen(valstr) + 1]; if( !arg ) CONSOLE.Warning(1, "error, failed to allocate memory for option"); else{ strcpy(arg, valstr); delete []arg_ctcs; arg_ctcs = arg; CTCS.Initial(); CTCS.Reset(1); } }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); if( !(msgbuf = strchr(msgbuf+11, ' ')) ) goto err; if(*++msgbuf != '.') cfg_seed_ratio = atof(msgbuf); if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err; if(*++msgbuf != '.') cfg_max_peers = atoi(msgbuf); if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err; if(*++msgbuf != '.') cfg_min_peers = atoi(msgbuf); if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err; if(*++msgbuf != '.'){ char *p = strchr(msgbuf, ' '); if( !p ) goto err; 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 ){ if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err; if(*++msgbuf != '.'){ cfg_cache_size = atoi(msgbuf); BTCONTENT.CacheConfigure(); } } if( m_protocol == 1 ){ if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err; ++msgbuf; // old cfg_exit_zero_peers option } if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err; if(*++msgbuf != '.'){ if(atoi(msgbuf)){ if( !WORLD.IsPaused() ) WORLD.Pause(); }else if( WORLD.IsPaused() ) WORLD.Resume(); } } delete []msgbuf; return 0; err: CONSOLE.Warning(2, "Malformed or invalid input from CTCS: %s", origmsg); delete []msgbuf; return -1;}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(arg_verbose) CONSOLE.Debug("Connected to CTCS"); 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( T_CONNECTING == m_status ){ FD_SET(m_sock, rfdp); FD_SET(m_sock, wfdp); }else if( INVALID_SOCKET != m_sock ){ if( now > m_statustime ) Report_Status(); 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(arg_verbose) CONSOLE.Debug("Connected to CTCS"); 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -