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 + -
显示快捷键?