console.cpp

来自「最经典的bittorrent协议的实现的源码」· C++ 代码 · 共 1,273 行 · 第 1/3 页

CPP
1,273
字号
  char checked[14] = "";  if( BTCONTENT.CheckedPieces() < BTCONTENT.GetNPieces() ){    sprintf( checked, "Checking: %d%%",      100 * BTCONTENT.CheckedPieces() / BTCONTENT.GetNPieces() );  }  char complete[8];  if( BTCONTENT.IsFull() )    sprintf(complete, "seeding");  else if( BTCONTENT.Seeding() )    sprintf(complete, "seed%d%%",      100 * BTCONTENT.pBF->Count() / BTCONTENT.GetNPieces());  else{    int have, avail, all;    BitField tmpBitfield = *BTCONTENT.pBF;    tmpBitfield.Except(*BTCONTENT.pBMasterFilter);    have = tmpBitfield.Count();    WORLD.Pieces_I_Can_Get(&tmpBitfield);    tmpBitfield.Except(*BTCONTENT.pBMasterFilter);    avail = tmpBitfield.Count();    all = BTCONTENT.GetNPieces() - BTCONTENT.pBMasterFilter->Count();    sprintf(complete, "%d/%d%%", 100 * have / all, 100 * avail / all);  }  long remain = -1;  char timeleft[20];  size_t rate;  if( !BTCONTENT.Seeding() || BTCONTENT.FlushFailed() ){  // downloading    if( rate = Self.RateDL() ){      // don't overflow remain      if( BTCONTENT.GetLeftBytes() < (uint64_t)rate << 22 )        remain = BTCONTENT.GetLeftBytes() / rate / 60;      else remain = 99999;    }  }else{  //seeding    if( cfg_seed_hours )      remain = cfg_seed_hours * 60 - (now - BTCONTENT.GetSeedTime()) / 60;    else if( rate = Self.RateUL() ){      // don't overflow remain      if( cfg_seed_ratio *          (Self.TotalDL() ? Self.TotalDL() : BTCONTENT.GetTotalFilesLength()) -          Self.TotalUL() < (uint64_t)rate << 22 )        remain = (long)( cfg_seed_ratio *          (Self.TotalDL() ? Self.TotalDL() : BTCONTENT.GetTotalFilesLength()) -          Self.TotalUL() ) / rate / 60;      else remain = 99999;    }  }  if( remain >= 0 ){    if( remain < 60000 )  // 1000 hours      snprintf(timeleft, sizeof(timeleft), "%d:%2.2d",        (int)(remain / 60), (int)(remain % 60));    else strcpy(timeleft, ">999hr");  }else strcpy(timeleft, "stalled");  snprintf(buffer, length,    "%c S:%d/%d L:%d/%d C:%d  R=%.2f D=%d U=%d K/s  %s %s  %s%s",    LIVE_CHAR[m_live_idx++],    (int)(WORLD.GetSeedsCount()),    (int)(Tracker.GetSeedsCount()) - (BTCONTENT.IsFull() ? 1 : 0),    (int)(WORLD.GetPeersCount()) - WORLD.GetSeedsCount() - WORLD.GetConnCount(),    (int)(Tracker.GetPeersCount()) - Tracker.GetSeedsCount() -      (!BTCONTENT.IsFull() ? 1 : 0),    (int)(WORLD.GetConnCount()),    (double)(Self.TotalUL()) / ( Self.TotalDL() ? Self.TotalDL() :                                 BTCONTENT.GetTotalFilesLength() ),    (int)(Self.RateDL() >> 10), (int)(Self.RateUL() >> 10),    complete, timeleft,    partial,    (Tracker.GetStatus()==T_CONNECTING) ? "Connecting" :      ( (Tracker.GetStatus()==T_READY) ? "Connected" :          (Tracker.IsQuitting() ? "Quitting" :           (WORLD.IsPaused() ? "Paused" : checked)) )  );}void Console::Print(const char *message, ...){  va_list ap;  if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||      m_streams[O_INPUT]->IsSuspended() ||      (!m_streams[O_NORMAL]->SameDev(m_streams[O_INTERACT]) &&       !m_streams[O_NORMAL]->SameDev(m_streams[O_INPUT])) ){    va_start(ap, message);    if( m_streams[O_NORMAL]->Output(message, ap) )      SyncNewlines(O_NORMAL);    va_end(ap);  }  if( arg_verbose && !m_streams[O_DEBUG]->SameDev(m_streams[O_NORMAL]) ){    va_start(ap, message);    if( m_streams[O_DEBUG]->Output(message, ap) )      SyncNewlines(O_DEBUG);    va_end(ap);  }}/* Print message without a terminating newline   With a null message, start/insure a new line*/void Console::Print_n(const char *message, ...){  va_list ap;  if( m_status_last && *message ) Print_n("");  m_status_last = 0;  if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||      m_streams[O_INPUT]->IsSuspended() ||      (!m_streams[O_NORMAL]->SameDev(m_streams[O_INTERACT]) &&       !m_streams[O_NORMAL]->SameDev(m_streams[O_INPUT])) ){    va_start(ap, message);    if( m_streams[O_NORMAL]->Output_n(message, ap) )      SyncNewlines(O_NORMAL);    va_end(ap);  }  if( arg_verbose && !m_streams[O_DEBUG]->SameDev(m_streams[O_NORMAL]) ){    va_start(ap, message);    if( m_streams[O_DEBUG]->Output_n(message, ap) )      SyncNewlines(O_DEBUG);    va_end(ap);  }}/* Update (replace) the current line (no terminating newline)*/void Console::Update(const char *message, ...){  va_list ap;  m_status_last = 0;  if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||      m_streams[O_INPUT]->IsSuspended() ||      (!m_streams[O_NORMAL]->SameDev(m_streams[O_INTERACT]) &&       !m_streams[O_NORMAL]->SameDev(m_streams[O_INPUT])) ){    va_start(ap, message);    if( m_streams[O_NORMAL]->Update(message, ap) )      SyncNewlines(O_NORMAL);    va_end(ap);  }  if( arg_verbose && !m_streams[O_DEBUG]->SameDev(m_streams[O_NORMAL]) ){    va_start(ap, message);    if( m_streams[O_DEBUG]->Update(message, ap) )      SyncNewlines(O_DEBUG);    va_end(ap);  }}/* "sev" indicates the severity of the message.   0: will be printed but not sent to CTCS   1: extremely urgent/important   2: less important   3: no problem*/void Console::Warning(int sev, const char *message, ...){  va_list ap;  va_start(ap, message);  if( m_streams[O_WARNING]->Output(message, ap) )    SyncNewlines(O_WARNING);  va_end(ap);  if( arg_verbose && !m_streams[O_DEBUG]->SameDev(m_streams[O_WARNING]) ){    va_start(ap, message);    if( m_streams[O_DEBUG]->Output(message, ap) )      SyncNewlines(O_DEBUG);    va_end(ap);  }  if(sev && arg_ctcs){    char cmsg[CTCS_BUFSIZE];    va_start(ap, message);    vsnprintf(cmsg, CTCS_BUFSIZE, message, ap);    CTCS.Send_Info(sev, cmsg);    va_end(ap);  }}void Console::Debug(const char *message, ...){  static char buffer[80];  if( !arg_verbose ) return;  char *format = (char *)0;  size_t buflen;  va_list ap;  if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||      m_streams[O_INPUT]->IsSuspended() ||      (!m_streams[O_DEBUG]->SameDev(m_streams[O_INTERACT]) &&       !m_streams[O_DEBUG]->SameDev(m_streams[O_INPUT])) ){    size_t need = strlen(message)+1 + 10*sizeof(unsigned long)/4;    if( need > sizeof(buffer) && (format = new char[need]) ) buflen = need;    else{ format = buffer; buflen = sizeof(buffer); }    snprintf(format, buflen, "%lu %s", (unsigned long)now, message);    va_start(ap, message);    if( m_streams[O_DEBUG]->Output(format, ap) )      SyncNewlines(O_DEBUG);    va_end(ap);    if( format && format != buffer ) delete []format;  }}/* Print debug message without a terminating newline   With a null message, start/insure a new line*/void Console::Debug_n(const char *message, ...){  static char buffer[80];  static int f_new_line = 1;  if( !arg_verbose ) return;  va_list ap;  if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||      m_streams[O_INPUT]->IsSuspended() ||      (!m_streams[O_DEBUG]->SameDev(m_streams[O_INTERACT]) &&       !m_streams[O_DEBUG]->SameDev(m_streams[O_INPUT])) ){    if( m_streams[O_DEBUG]->SameDev(m_streams[O_NORMAL]) ){      if( m_status_last && *message ) Debug_n("");      m_status_last = 0;    }    if( f_new_line && *message ){      char *format = (char *)0;      size_t buflen;      size_t need = strlen(message)+1 + 10*sizeof(unsigned long)/4;      if( need > sizeof(buffer) && (format = new char[need]) ) buflen = need;      else{ format = buffer; buflen = sizeof(buffer); }      snprintf(format, buflen, "%lu %s", (unsigned long)now, message);      va_start(ap, message);      if( m_streams[O_DEBUG]->Output_n(format, ap) )        SyncNewlines(O_DEBUG);      va_end(ap);      if( format && format != buffer ) delete []format;    }else{      va_start(ap, message);      if( m_streams[O_DEBUG]->Output_n(message, ap) )        SyncNewlines(O_DEBUG);      va_end(ap);    }    if( *message ) f_new_line = 0;    else f_new_line = 1;  }}void Console::Interact(const char *message, ...){  va_list ap;  va_start(ap, message);  if( m_streams[O_INTERACT]->Output(message, ap) )    SyncNewlines(O_INTERACT);  va_end(ap);}/* Print interactive message without a terminating newline   With a null message, start/insure a new line*/void Console::Interact_n(const char *message, ...){  va_list ap;  if( m_streams[O_INTERACT]->SameDev(m_streams[O_NORMAL]) ){    if( m_status_last && *message ) Interact_n("");    m_status_last = 0;  }  va_start(ap, message);  if( m_streams[O_INTERACT]->Output_n(message, ap) )    SyncNewlines(O_INTERACT);  va_end(ap);}/* Update (replace) the current interactive line (no terminating newline)*/void Console::InteractU(const char *message, ...){  va_list ap;  if( m_streams[O_INTERACT]->SameDev(m_streams[O_NORMAL]) ){    if( m_status_last ) Interact_n("");    m_status_last = 0;  }  va_start(ap, message);  if( m_streams[O_INTERACT]->Update(message, ap) )    SyncNewlines(O_INTERACT);  va_end(ap);}// Avoid using this during normal operation, as it blocks for input!char *Console::Input(const char *prompt, char *field, size_t length){  char *retval;  m_streams[O_INPUT]->SetInputMode(K_LINES);  Interact_n(0, "");  Interact_n(0, "%s", prompt);  retval = m_streams[O_INPUT]->Input(field, length);  m_streams[O_INPUT]->SetInputMode(K_CHARS);  return retval;}void Console::SyncNewlines(int master){  for( int i=0; i < O_NCHANNELS; i++ ){    if( i != master && m_streams[i]->SameDev(m_streams[master]) )      m_streams[i]->SyncNewline(m_streams[master]);  }}RETSIGTYPE Console::Signal(int sig_no){  switch( sig_no ){  case SIGTTOU:    for( int i=0; i < O_NCHANNELS; i++ )      if( m_streams[i]->IsTTY() ) m_streams[i]->Suspend();    m_conmode = m_streams[O_INPUT]->GetInputMode();    break;  case SIGTTIN:    if( m_streams[O_INPUT]->IsTTY() ) m_streams[O_INPUT]->Suspend();    m_conmode = m_streams[O_INPUT]->GetInputMode();    break;  case SIGCONT:    for( int i=0; i <= O_NCHANNELS; i++ )      if( m_streams[i]->IsTTY() ) m_streams[i]->Resume();    m_streams[O_INPUT]->SetInputMode(m_conmode);    // restore my handler    signal(SIGTSTP, signals);    break;  case SIGTSTP:    m_conmode = m_streams[O_INPUT]->GetInputMode();    m_streams[O_INPUT]->RestoreMode();    // let the system default action proceed    signal(sig_no, SIG_DFL);    raise(sig_no);    break;  default:    break;  }}void Console::Daemonize(){#ifdef HAVE_WORKING_FORK  size_t orig_cache_size = 0;  pid_t r;  if( cfg_cache_size && BTCONTENT.CacheUsed() ){    orig_cache_size = cfg_cache_size;    cfg_cache_size /= 2;    BTCONTENT.CacheConfigure();  }  if( (r = fork()) < 0 ){    CONSOLE.Warning(2, "warn, fork to background failed:  %s", strerror(errno));    arg_daemon = 0;    goto restorecache;  }else if(r) exit(EXIT_SUCCESS);  arg_daemon = 1;  for( int i=0; i <= O_NCHANNELS; i++ ){    if( m_streams[i]->IsTTY() && ChangeChannel(i, "off") < 0 )      m_streams[i]->Suspend();  }  if( m_stdout.IsTTY() ) m_stdout.Close();  if( m_stderr.IsTTY() ) m_stderr.Close();  if( m_stdin.IsTTY() ) m_stdin.Close();  if( setsid() < 0 ){    CONSOLE.Warning(2,      "warn, failed to create new session (continuing in background):  %s",      strerror(errno));    goto restorecache;  }  if( (r = fork()) < 0 ){    CONSOLE.Warning(2,      "warn, final fork failed (continuing in background):  %s",      strerror(errno));    goto restorecache;  }else if(r) exit(EXIT_SUCCESS);  else if(arg_verbose) Debug("Running in daemon (background) mode."); restorecache:  if( orig_cache_size ){    cfg_cache_size = orig_cache_size;    BTCONTENT.CacheConfigure();  }#endif}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?