📄 tracker.cpp
字号:
h = gethostbyname(cfg_public_ip); memcpy(&addr.sin_addr, h->h_addr, sizeof(struct in_addr)); } Self.SetIp(addr); goto next_step; } if( cfg_listen_ip ){ // Get specified listen address. addr.sin_addr.s_addr = cfg_listen_ip; Self.SetIp(addr); if( !IsPrivateAddress(cfg_listen_ip) ) goto next_step; } { // Try to get address corresponding to the hostname. struct hostent *h; char hostname[MAXHOSTNAMELEN]; if( gethostname(hostname, MAXHOSTNAMELEN) >= 0 ){// CONSOLE.Debug("hostname: %s", hostname); if( h = gethostbyname(hostname) ){// CONSOLE.Debug("Host name: %s", h->h_name);// CONSOLE.Debug("Address: %s", inet_ntoa(*((struct in_addr *)h->h_addr))); if( !IsPrivateAddress(((struct in_addr *)(h->h_addr))->s_addr) || !cfg_listen_ip ){ memcpy(&addr.sin_addr, h->h_addr, sizeof(struct in_addr)); Self.SetIp(addr); } } } } next_step: if( BuildBaseRequest() < 0 ) return -1; return 0;}int btTracker::IsPrivateAddress(uint32_t addr){ return (addr & htonl(0xff000000)) == htonl(0x0a000000) || // 10.x.x.x/8 (addr & htonl(0xfff00000)) == htonl(0xac100000) || // 172.16.x.x/12 (addr & htonl(0xffff0000)) == htonl(0xc0a80000) || // 192.168.x.x/16 (addr & htonl(0xff000000)) == htonl(0x7f000000); // 127.x.x.x/8}int btTracker::BuildBaseRequest(){ char ih_buf[20 * 3 + 1], pi_buf[20 * 3 + 1], tmppath[MAXPATHLEN]; const char *format; strcpy(tmppath,m_path); if(strchr(m_path, '?')) format=REQ_URL_P1A_FMT; else format=REQ_URL_P1_FMT; char *opt = (char *)0; if( cfg_public_ip ){ opt = new char[5+strlen(cfg_public_ip)]; strcpy(opt, "&ip="); strcat(opt, cfg_public_ip); }else{ struct sockaddr_in addr; Self.GetAddress(&addr); if( !IsPrivateAddress(addr.sin_addr.s_addr) ){ opt = new char[20]; strcpy(opt, "&ip="); strcat(opt, inet_ntoa(addr.sin_addr)); } } if(MAXPATHLEN < snprintf((char*)m_path,MAXPATHLEN,format, tmppath, Http_url_encode(ih_buf,(char*)BTCONTENT.GetInfoHash(),20), Http_url_encode(pi_buf,(char*)BTCONTENT.GetPeerId(),20), opt ? opt : "", cfg_listen_port, m_key)){ return -1; } return 0;}int btTracker::Connect(){ ssize_t r; time(&m_last_timestamp); if(_s2sin(m_host,m_port,&m_sin) < 0) { CONSOLE.Warning(2, "warn, get tracker's ip address failed."); return -1; } m_sock = socket(AF_INET,SOCK_STREAM,0); if(INVALID_SOCKET == m_sock) return -1; // we only need to bind if we have specified an ip // we need it to bind here before the connect!!!! if ( cfg_listen_ip != 0 ) { struct sockaddr_in addr; // clear the struct as requested in the manpages memset(&addr,0, sizeof(sockaddr_in)); // set the type addr.sin_family = AF_INET; // we want the system to choose port addr.sin_port = 0; // set the defined ip from the commandline addr.sin_addr.s_addr = cfg_listen_ip; // bind it or return... if(bind(m_sock,(struct sockaddr*)&addr,sizeof(struct sockaddr_in)) != 0){ CONSOLE.Warning(1, "warn, can't set up tracker connection: %s", strerror(errno)); 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{ if(arg_verbose) CONSOLE.Debug("Connected to tracker"); if( 0 == SendRequest() ) m_status = T_READY; else{ CLOSE_SOCKET(m_sock); return -1; } } return 0;}int btTracker::SendRequest(){ char *event,*str_event[] = {"started","stopped","completed" }; char REQ_BUFFER[2*MAXPATHLEN]; struct sockaddr_in addr; if( m_f_stoped ) event = str_event[1]; /* stopped */ else if( !m_f_started ){ if( BTCONTENT.IsFull() ) m_f_completed = 1; event = str_event[0]; /* started */ }else if( BTCONTENT.IsFull() && !m_f_completed ){ if( Self.TotalDL() > 0 ) event = str_event[2]; /* download complete */ else event = (char*) 0; /* interval */ m_f_completed = 1; /* only send download complete once */ }else event = (char*) 0; /* interval */ char opt1[20] = "&event="; char opt2[12+PEER_ID_LEN] = "&trackerid="; if( BTCONTENT.IsFull() ) m_totaldl = Self.TotalDL(); if(MAXPATHLEN < snprintf(REQ_BUFFER,MAXPATHLEN,REQ_URL_P2_FMT, m_path, event ? strncat(opt1,event,12) : "", *m_trackerid ? strncat(opt2,m_trackerid,PEER_ID_LEN) : "", (unsigned long long)(m_totalul = Self.TotalUL()), (unsigned long long)m_totaldl, (unsigned long long)(BTCONTENT.GetLeftBytes()), (int)cfg_max_peers)){ return -1; } // if we have a tracker hostname (not just an IP), send a Host: header if(_IPsin(m_host, m_port, &addr) < 0){ char REQ_HOST[MAXHOSTNAMELEN]; if(MAXHOSTNAMELEN < snprintf(REQ_HOST,MAXHOSTNAMELEN,"\r\nHost: %s",m_host)) return -1; strcat(REQ_BUFFER, REQ_HOST); } strcat(REQ_BUFFER, "\r\nUser-Agent: "); strcat(REQ_BUFFER, cfg_user_agent); strcat(REQ_BUFFER,"\r\n\r\n"); // hc //CONSOLE.Warning(0, "SendRequest: %s", REQ_BUFFER); if( 0 != m_request_buffer.PutFlush(m_sock,REQ_BUFFER,strlen((char*)REQ_BUFFER)) ){ CONSOLE.Warning(2, "warn, send request to tracker failed: %s", strerror(errno)); if( event == str_event[2] ) m_f_completed = 0; // failed sending completion event return -1; }else{ m_report_time = now; m_report_dl = m_totaldl; m_report_ul = m_totalul; if(arg_verbose) CONSOLE.Debug("Reported to tracker: %llu uploaded, %llu downloaded", (unsigned long long)m_report_ul, (unsigned long long)m_report_dl); } return 0;}int btTracker::IntervalCheck(fd_set *rfdp, fd_set *wfdp){ /* tracker communication */ 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 || // Connect to tracker early if we run low on peers. (WORLD.GetPeersCount() < cfg_min_peers && m_prevpeers >= cfg_min_peers && now - m_last_timestamp >= 15) ){ m_prevpeers = WORLD.GetPeersCount(); 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; // time reversed }else if( T_CONNECTING == m_status ){ FD_SET(m_sock, rfdp); FD_SET(m_sock, wfdp); }else if( INVALID_SOCKET != m_sock ){ FD_SET(m_sock, rfdp); if( m_request_buffer.Count() ) FD_SET(m_sock, wfdp); } return m_sock;}int btTracker::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 ){ if( ECONNREFUSED == error ){ if(arg_verbose) CONSOLE.Debug("tracker connection refused"); m_connect_refuse_click++; }else CONSOLE.Warning(2, "warn, connect to tracker failed: %s", strerror(error)); Reset(15); return -1; }else{ if(arg_verbose) CONSOLE.Debug("Connected to tracker"); if( SendRequest() == 0 ) m_status = T_READY; else { Reset(15); 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 tracker 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 = CheckReponse(); 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( m_request_buffer.Count() && m_request_buffer.FlushOut(m_sock) < 0 ){ Reset(15); return -1; } } }else{ // failsafe Reset(15); return -1; } return 0;}void btTracker::Restart(){ m_f_stoped = m_f_restart = 0; if( T_FINISHED == m_status ){ m_status = T_FREE; m_f_started = 0; m_interval = 15; }}void btTracker::SetStoped(){ if( !m_f_started ){ m_f_stoped = 1; m_status = T_FINISHED; }else{ Reset(15); m_f_stoped = 1; }}void btTracker::RestartTracker(){ SetStoped(); // finish the tracker // Now we need to wait until the tracker updates (T_FINISHED == m_status), // then Tracker.Restart(). SetRestart();}size_t btTracker::GetPeersCount() const { // includes seeds, so must always be >= 1 (myself!) return (m_peers_count > m_seeds_count) ? m_peers_count : (GetSeedsCount() + (BTCONTENT.IsFull() ? 0 : 1));}size_t btTracker::GetSeedsCount() const{ return m_seeds_count ? m_seeds_count : (BTCONTENT.IsFull() ? 1 : 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -