tracker.cpp

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

CPP
615
字号
#include "tracker.h"#ifndef WINDOWS#include <unistd.h>#include <netdb.h>#endif#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"#ifndef HAVE_SNPRINTF#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;}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 ){    CLOSE_SOCKET(m_sock);    m_sock = INVALID_SOCKET;  }  m_reponse_buffer.Reset();  time(&m_last_timestamp);  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 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) {      // if peer is not us      if( !Self.IpEquiv(*(struct sockaddr_in *)ps) ){        memcpy(&addr.sin_addr,ps,sizeof(struct in_addr));        memcpy(&addr.sin_port,ps+sizeof(struct in_addr),sizeof(unsigned short));        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(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);  if( r > 0 ) return 0;  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( (-1 == r) ? 15 : 0 );    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);}

⌨️ 快捷键说明

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