📄 tracker.cpp
字号:
#include "tracker.h"#include <inttypes.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include "peerlist.h"#include "peer.h"#include "httpencode.h"#include "bencode.h"#include "setnonblock.h"#include "connect_nonb.h"#include "btcontent.h"#include "iplist.h"#include "btconfig.h"#include "ctcs.h"#include "console.h"#include "bttime.h"#if !defined(HAVE_SNPRINTF) || !defined(HAVE_RANDOM)#include "compat.h"#endifbtTracker Tracker;btTracker::btTracker(){ memset(m_host,0,MAXHOSTNAMELEN); memset(m_path,0,MAXPATHLEN); memset(m_trackerid,0,PEER_ID_LEN+1); m_sock = INVALID_SOCKET; m_port = 80; m_status = T_FREE; m_f_started = m_f_stoped = m_f_completed = m_f_restart = 0; m_interval = 15; m_peers_count = m_seeds_count = 0; m_connect_refuse_click = 0; m_last_timestamp = (time_t) 0; m_prevpeers = 0; m_report_time = (time_t) 0; m_report_dl = m_report_ul = m_totaldl = m_totalul = 0;}btTracker::~btTracker(){ if( m_sock != INVALID_SOCKET) CLOSE_SOCKET(m_sock);}void btTracker::Reset(time_t new_interval){ if(new_interval) m_interval = new_interval; if( INVALID_SOCKET != m_sock ){ if(arg_verbose && T_READY==m_status) CONSOLE.Debug("Disconnected from tracker"); CLOSE_SOCKET(m_sock); m_sock = INVALID_SOCKET; } m_request_buffer.Reset(); m_reponse_buffer.Reset(); if( now < m_last_timestamp ) m_last_timestamp = now; // time reversed if( m_f_stoped ){ m_status = T_FINISHED; if( m_f_restart ) Restart(); } else m_status = T_FREE;}int btTracker:: _IPsin(char *h, int p, struct sockaddr_in *psin){ psin->sin_family = AF_INET; psin->sin_port = htons(p); psin->sin_addr.s_addr = inet_addr(h); return ( psin->sin_addr.s_addr == INADDR_NONE ) ? -1 : 0;}int btTracker:: _s2sin(char *h,int p,struct sockaddr_in *psin){ psin->sin_family = AF_INET; psin->sin_port = htons(p); if( h ){ psin->sin_addr.s_addr = inet_addr(h); if(psin->sin_addr.s_addr == INADDR_NONE){ struct hostent *ph = gethostbyname(h); if( !ph || ph->h_addrtype != AF_INET){ memset(psin,0,sizeof(struct sockaddr_in)); return -1; } memcpy(&psin->sin_addr,ph->h_addr_list[0],sizeof(struct in_addr)); } }else psin->sin_addr.s_addr = htonl(INADDR_ANY); return 0;}int btTracker::_UpdatePeerList(char *buf,size_t bufsiz){ char tmphost[MAXHOSTNAMELEN]; const char *ps; size_t i,pos,tmpport; size_t cnt = 0; struct sockaddr_in addr; if( decode_query(buf,bufsiz,"failure reason",&ps,&i,(int64_t*)0,QUERY_STR) ){ char failreason[1024]; if( i < 1024 ){ memcpy(failreason, ps, i); failreason[i] = '\0'; }else{ memcpy(failreason, ps, 1000); failreason[1000] = '\0'; strcat(failreason,"..."); } CONSOLE.Warning(1, "TRACKER FAILURE REASON: %s", failreason); return -1; } if( decode_query(buf,bufsiz,"warning message",&ps,&i,(int64_t*)0,QUERY_STR) ){ char warnmsg[1024]; if( i < 1024 ){ memcpy(warnmsg, ps, i); warnmsg[i] = '\0'; }else{ memcpy(warnmsg, ps, 1000); warnmsg[1000] = '\0'; strcat(warnmsg,"..."); } CONSOLE.Warning(2, "TRACKER WARNING: %s", warnmsg); } m_peers_count = m_seeds_count = 0; if( decode_query(buf,bufsiz,"tracker id",&ps,&i,(int64_t*)0,QUERY_STR) ){ if( i <= PEER_ID_LEN ){ memcpy(m_trackerid, ps, i); m_trackerid[i] = '\0'; }else{ memcpy(m_trackerid, ps, PEER_ID_LEN); m_trackerid[PEER_ID_LEN] = '\0'; } } if( !decode_query(buf, bufsiz, "interval", (const char**)0, &i, (int64_t*)0, QUERY_INT) ) return -1; if(m_interval != (time_t)i) m_interval = (time_t)i; if(m_default_interval != (time_t)i) m_default_interval = (time_t)i; if( decode_query(buf, bufsiz, "complete", (const char**)0, &i, (int64_t*)0, QUERY_INT) ) m_seeds_count = i; if( decode_query(buf, bufsiz, "incomplete", (const char**)0, &i, (int64_t*)0, QUERY_INT) ) m_peers_count = m_seeds_count + i; else{ if(arg_verbose && 0==m_seeds_count) CONSOLE.Debug("Tracker did not supply peers count."); m_peers_count = m_seeds_count; } pos = decode_query(buf, bufsiz, "peers", (const char**)0, (size_t *)0, (int64_t*)0, QUERY_POS); if( !pos ){ return -1; } if(4 > bufsiz - pos){ return -1; } // peers list ̫С buf += (pos + 1); bufsiz -= (pos + 1); ps = buf-1; if( *ps != 'l' ){ // binary peers section if not 'l' addr.sin_family = AF_INET; i = 0; while( *ps != ':' ) i = i * 10 + (*ps++ - '0'); i /= 6; ps++; while( i-- > 0 ){ memcpy(&addr.sin_addr,ps,sizeof(struct in_addr)); memcpy(&addr.sin_port,ps+sizeof(struct in_addr),sizeof(unsigned short)); if( !Self.IpEquiv(addr) ){ cnt++; IPQUEUE.Add(&addr); } ps += 6; } } else for( ; bufsiz && *buf!='e'; buf += pos, bufsiz -= pos ){ pos = decode_dict(buf,bufsiz,(char*)0); if(!pos) break; if( !decode_query(buf,pos,"ip",&ps,&i,(int64_t*)0,QUERY_STR) || MAXHOSTNAMELEN < i ) continue; memcpy(tmphost,ps,i); tmphost[i] = '\0'; if( !decode_query(buf,pos,"port",(const char**)0,&tmpport,(int64_t*)0, QUERY_INT) ) continue; if( !decode_query(buf,pos,"peer id",&ps,&i,(int64_t*)0,QUERY_STR) && i != 20 ) continue; if(_IPsin(tmphost,tmpport,&addr) < 0){ CONSOLE.Warning(3, "warn, detected invalid ip address %s.",tmphost); continue; } if( !Self.IpEquiv(addr) ){ cnt++; IPQUEUE.Add(&addr); } } if( 0==m_peers_count ){ m_peers_count = cnt + 1; // include myself m_f_boguspeercnt = 1; }else m_f_boguspeercnt = 0; if(arg_verbose) CONSOLE.Debug("new peers=%d; next check in %d sec", (int)cnt, (int)m_interval); return 0;}int btTracker::CheckReponse(){ char *pdata, *format; ssize_t r; size_t q, hlen, dlen; r = m_reponse_buffer.FeedIn(m_sock); time(&m_last_timestamp); if( r > 0 ) return 0; // connection is still open; may have more data coming q = m_reponse_buffer.Count(); if( !q ){ int error = 0; socklen_t n = sizeof(error); if( getsockopt(m_sock, SOL_SOCKET,SO_ERROR,&error,&n) < 0 ) error = errno; if( error != 0 ) CONSOLE.Warning(2, "warn, received nothing from tracker: %s", strerror(error)); else CONSOLE.Warning(2, "warn, received nothing from tracker!"); Reset(15); // try again return -1; } Reset( (-1 == r) ? 15 : 0 ); // can't reset socket before error check hlen = Http_split(m_reponse_buffer.BasePointer(), q, &pdata,&dlen); if( !hlen ){ CONSOLE.Warning(2, "warn, tracker reponse invalid. No html header found."); return -1; } r = Http_reponse_code(m_reponse_buffer.BasePointer(),hlen); if ( r != 200 ){ if( r == 301 || r == 302 ){ char redirect[MAXPATHLEN], ih_buf[20 * 3 + 1], pi_buf[20 * 3 + 1], tmppath[MAXPATHLEN]; if( Http_get_header(m_reponse_buffer.BasePointer(), hlen, "Location", redirect) < 0 ) return -1; if( Http_url_analyse(redirect,m_host,&m_port,m_path) < 0 ){ CONSOLE.Warning(1, "warn, tracker redirected to an invalid url %s", redirect); return -1; }else{ char *c = strstr(m_path, "?info_hash="); if( !c ) c = strstr(m_path, "&info_hash="); if( c ) *c = '\0'; if(arg_verbose) CONSOLE.Debug("tracker redirect to %s", redirect); if( BuildBaseRequest() < 0 ) return -1; } if( Connect() < 0 ){ Reset(15); return -1; }else return 0; }else if( r >= 400 ){ CONSOLE.Warning(2, "Tracker reponse code >= 400 !!!"); CONSOLE.Warning(2, "The file is not registered on this tracker or may have been removed."); CONSOLE.Warning(2, "IF YOU CONTINUE TO GET THIS MESSAGE AND DOWNLOAD DOES NOT BEGIN, PLEASE STOP CTORRENT!"); if( pdata && dlen ){ // write(STDERR_FILENO, pdata, dlen); CONSOLE.Warning(0, "Tracker reponse data DUMP:"); CONSOLE.Warning(0, "%s", pdata); CONSOLE.Warning(0, "== DUMP OVER=="); } return -1; }else return 0; } if( !m_f_started ) m_f_started = 1; m_connect_refuse_click = 0; m_ok_click++; if ( !pdata ){ CONSOLE.Warning(2, "warn, peers list received from tracker is empty."); return 0; } return _UpdatePeerList(pdata,dlen);}int btTracker::Initial(){ if(Http_url_analyse(BTCONTENT.GetAnnounce(),m_host,&m_port,m_path) < 0){ CONSOLE.Warning(1, "error, invalid tracker url format!"); return -1; } char chars[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for(int i=0; i<8; i++) m_key[i] = chars[random()%36]; m_key[8] = 0; /* get local ip address */ struct sockaddr_in addr; if( cfg_public_ip ){ // Get specified public address. if( (addr.sin_addr.s_addr = inet_addr(cfg_public_ip)) == INADDR_NONE ){ struct hostent *h;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -