int btTracker::SendRequest() { struct sockaddr_in addr; char REQ_BUFFER[2 * MAXPATHLEN] = {'\0'}; const char *str_event[] = {"started", "stopped", "completed"}; char *event; if (m_f_stoped) event = (char *) str_event[1]; /* stopped */ else if (!m_f_started) { if (BTCONTENT.IsFull()) m_f_completed = 1; event = (char *) str_event[0]; /* started */ } else if (BTCONTENT.IsFull() && !m_f_completed) { if (Self.TotalDL() > 0) event = (char *) 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); } strncat(REQ_BUFFER, "\r\nUser-Agent: ", 14 + 1); strncat(REQ_BUFFER, cfg_user_agent, strlen(cfg_user_agent)); strncat(REQ_BUFFER, "\r\n\r\n", 4 + 1); // 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::SendRequest() { enum{ DT_NONE, DT_STARTED, DT_STOPPED, DT_COMPLETED } event = DT_NONE; const char *event_str = (char *)0; char *req_buffer; struct sockaddr_in addr; dt_datalen_t totaldl, totalul; int r; if( !(req_buffer = new char[strlen(m_spec->request) + strlen(m_spec->host) + strlen(*cfg_user_agent) + 256]) ){ errno = ENOMEM; CONSOLE.Warning(1, "Error constructing tracker request: %s", strerror(errno)); return -1; } if( m_f_stop ) event = DT_STOPPED; else if( !m_f_started ){ if( BTCONTENT.IsFull() ) m_f_completed = 1; event = DT_STARTED; }else if( BTCONTENT.IsFull() && !m_f_completed ){ if( Self.TotalDL() > 0 ) event = DT_COMPLETED; m_f_completed = 1; // only send download complete once } totaldl = TRACKER.GetTotalDL(); totalul = TRACKER.GetTotalUL(); sprintf(req_buffer, "%s&uploaded=%llu&downloaded=%llu&left=%llu&compact=1&numwant=%d", m_spec->request, (unsigned long long)totalul, (unsigned long long)totaldl, (unsigned long long)BTCONTENT.GetLeftBytes(), (int)*cfg_max_peers); if( DT_NONE != event ){ strcat(req_buffer, "&event="); event_str = (DT_STARTED == event ? "started" : (DT_STOPPED == event ? "stopped" : (DT_COMPLETED == event ? "completed" : "update"))); strcat(req_buffer, event_str); } if( *m_trackerid ){ strcat(req_buffer, "&trackerid="); strcat(req_buffer, m_trackerid); } strcat(req_buffer, " HTTP/1.0" CRLF); // If we have a tracker hostname (not just an IP), send a Host: header if( _IPsin(m_spec->host, m_spec->port, &addr) < 0 ){ strcat(req_buffer, "Host: "); strcat(req_buffer, m_spec->host); strcat(req_buffer, CRLF); } strcat(req_buffer, "User-Agent: "); strcat(req_buffer, *cfg_user_agent); strcat(req_buffer, CRLF); strcat(req_buffer, CRLF); //CONSOLE.Warning(0, "SendRequest: %s", req_buffer); r = m_request_buffer.PutFlush(m_sock, req_buffer, strlen(req_buffer)); delete []req_buffer; if( r < 0 ){ CONSOLE.Warning(2, "warn, send request to tracker at %s failed: %s", m_spec->url, strerror(errno)); if( event == DT_COMPLETED ) m_f_completed = 0; // failed sending completion event return -1; }else{ if( 0==m_request_buffer.Count() ) shutdown(m_sock, SHUT_WR); m_report_time = now; m_report_dl = totaldl; m_report_ul = totalul; if(*cfg_verbose){ CONSOLE.Debug("Reported to tracker: %llu uploaded, %llu downloaded (%s)", (unsigned long long)m_report_ul, (unsigned long long)m_report_dl, event_str ? event_str : "update"); } } return 0; }
int btTracker::_UpdatePeerList(char *buf, size_t bufsiz) { char tmphost[MAXHOSTNAMELEN + 1] = {'\0'}; char warnmsg[1024] = {'\0'}; char failreason[1024] = {'\0'}; const char *ps = NULL; size_t i, pos, tmpport; size_t cnt = 0; struct sockaddr_in addr = {0, 0, {0}, {0}}; memset((void *) &addr, 0, sizeof(addr)); if (decode_query(buf, bufsiz, "failure reason", &ps, &i, (int64_t *) 0, QUERY_STR)) { 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)) { 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; }
dt_result_t btTracker::ParseResponse(const char *buf, size_t bufsiz) { char tmphost[MAXHOSTNAMELEN]; const char *ps; size_t i, pos, tmpport; int64_t bint; dt_count_t cnt = 0; struct sockaddr_in addr; if( decode_query(buf, bufsiz, "failure reason", &ps, &i, (int64_t *)0, DT_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 from %s: %s", m_spec->url, failreason); return DT_FAILURE; } if( decode_query(buf, bufsiz, "warning message", &ps, &i, (int64_t *)0, DT_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 from %s: %s", m_spec->url, warnmsg); } m_peers_count = m_seeds_count = 0; if( decode_query(buf, bufsiz, "tracker id", &ps, &i, (int64_t *)0, DT_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, NULL, &bint, DT_QUERY_INT) ){ m_interval = m_default_interval = (time_t)bint; }else{ CONSOLE.Debug("Tracker at %s did not specify interval.", m_spec->url); m_interval = m_default_interval; } if( decode_query(buf, bufsiz, "complete", (const char **)0, NULL, &bint, DT_QUERY_INT) ){ m_seeds_count = bint; } if( decode_query(buf, bufsiz, "incomplete", (const char **)0, NULL, &bint, DT_QUERY_INT) ){ m_peers_count = m_seeds_count + bint; }else{ if( *cfg_verbose && 0==m_seeds_count ) CONSOLE.Debug("Tracker at %s did not supply peers count.", m_spec->url); m_peers_count = m_seeds_count; } pos = decode_query(buf, bufsiz, "peers", (const char **)0, (size_t *)0, (int64_t *)0, DT_QUERY_POS); if( !pos ){ CONSOLE.Debug("Tracker at %s did not supply peers.", m_spec->url); return DT_FAILURE; } if( 4 > bufsiz - pos ){ CONSOLE.Debug("Tracker at %s supplied an invalid peers list.", m_spec->url); return DT_FAILURE; } 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, DT_QUERY_STR) || MAXHOSTNAMELEN < i ){ continue; } memcpy(tmphost, ps, i); tmphost[i] = '\0'; if( !decode_query(buf, pos, "port", (const char **)0, NULL, &bint, DT_QUERY_INT) ){ continue; } tmpport = bint; if( !decode_query(buf, pos, "peer id", &ps, &i, (int64_t *)0, DT_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(*cfg_verbose) CONSOLE.Debug("new peers=%d; next check in %d sec [%s]", (int)cnt, (int)m_interval, m_spec->url); return DT_SUCCESS; }