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