📄 tcptracker.cpp
字号:
/*************************************************************************** * Copyright (C) 2005-2006 Gao Xianchao * * 2007 Gao Xianchao gnap_an linux_lyb ahlongxp * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************//* * Author: gxc * Create data: 2005-10-07 20:09 */ #include <unistd.h> #include <arpa/inet.h>#include <curl/curl.h>#include <string>#include <iostream>#include "TCPTracker.h"#include "bdict.h"#include "blist.h"#include "binteger.h"#include "bstring.h"#include "log.h"#include "utils.h"size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp){ CTCPTracker* tracker = (CTCPTracker*)userp; std::string str; str.append((char*)buffer, size * nmemb); tracker->addResponse(str); return size * nmemb;}CTCPTracker::CTCPTracker(){ _complete_peer = 0; _total_peer = 0; _interval = 0; _nextUpdateTick = GetTickCount(); _startEventSend = false; _completeEventSend = false; }CTCPTracker::~CTCPTracker(){}void CTCPTracker::update(){ CURL* handle = curl_easy_init(); _tracker_response.clear(); _state = TS_CONNECTING; _state_str = "connecting"; _currentEvent = getCurrentEvent(); std::string url = makeTrackerUrl(event2Str(_currentEvent)); curl_easy_setopt(handle, CURLOPT_URL, url.c_str()); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(handle, CURLOPT_WRITEDATA, this); curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(handle, CURLOPT_TIMEOUT, 15); CURLcode ret = curl_easy_perform(handle); if(ret == CURLE_OK) { parseResponse(); } else { _state = TS_ERROR; _state_str = curl_easy_strerror(ret); LOG_INFO("TCPTracker Error(curl) : "<<_state_str); _nextUpdateTick = GetTickCount() + 60*1000; } curl_easy_cleanup(handle);}void CTCPTracker::stop(){}bool CTCPTracker::isProtocolSupported(const char* protocolName){ if(strcmp("http", protocolName) == 0 || strcmp("HTTP", protocolName) == 0) { return true; } return false;}void CTCPTracker::setUrl(const char* url){ _url = url;}TTrackerState CTCPTracker::getState(){ return _state;}void CTCPTracker::addResponse(std::string content){ _tracker_response += content;}void CTCPTracker::parseResponse(){ CBDict dict; int ret = dict.parse((const char*)_tracker_response.c_str(), _tracker_response.size()); if(ret <= 0) { LOG_INFO("_tracker_response parse error"); _state = TS_ERROR; _state_str = "can not parse _tracker_responser"; _nextUpdateTick = GetTickCount() + 60*1000; return; } LOG_DEBUG("tracker "<<_url); CBString* str = (CBString*)dict.getValue("failure reason"); if(str != NULL) { LOG_INFO("tracker return failure reason : " << str->getValue()); _state = TS_ERROR; _state_str = str->getValue(); _nextUpdateTick = GetTickCount() + 60*1000; return; } CBInteger* interval = (CBInteger*)dict.getValue("interval"); if(interval != NULL) { _interval = interval->getValue(); LOG_INFO("tracker return interval : " << interval->getValue()); } CBInteger* done = (CBInteger*)dict.getValue("done peers"); CBInteger* total = (CBInteger*)dict.getValue("num peers"); if(done != NULL && total != NULL) { _complete_peer = (int)done->getValue(); _total_peer = (int)total->getValue(); } // another type extension CBInteger* complete = (CBInteger*)dict.getValue("complete"); CBInteger* incomplete = (CBInteger*)dict.getValue("incomplete"); if(complete != NULL && incomplete != NULL) { _complete_peer = (int)complete->getValue(); _total_peer = _complete_peer + (int)incomplete->getValue(); } LOG_INFO("tracker return _complete_peer = " << _complete_peer); LOG_INFO("tracker return _total_peer = " << _total_peer); // Peers unsigned int peerCount = 0; CBObject* peersObj = (CBList*)dict.getValue("peers"); if(peersObj != NULL && peersObj->getType() == 3) { CBList* peers = (CBList*)peersObj; peerCount = peers->getCount(); //LOG_INFO("tracker return " << count << " peers "); for(unsigned int i=0; i<peerCount; ++i) { CBDict* peer = (CBDict*)peers->getValue(i); //CBString* id = (CBString*)peer->getValue("peer id"); //LOG_DEBUG("peer id = " << id->getValue()); CBString* ip = (CBString*)peer->getValue("ip"); //LOG_DEBUG("ip = "<<ip->getValue()); CBInteger* port = (CBInteger*)peer->getValue("port"); //LOG_DEBUG("port = "<<port->getValue()); _trackerManager->getBTTask()->getPeerManager()->addPeerInfoWithoutID(ip->getValue().c_str(), port->getValue()); } } if(peersObj != NULL && peersObj->getType() == 2) { CBString* peers = (CBString*)peersObj; std::string peerStr = peers->getValue(); if(peerStr.size() % 6 == 0) { for(unsigned int i=0; i<peerStr.size()/6; ++i) { unsigned int ip =*( (unsigned int*)(peerStr.data()+i*6)); unsigned short port =*( (unsigned short*)(peerStr.data()+i*6+4)); port = ntohs(port); char ipBuf[256]; std::string ipStr = inet_ntop(AF_INET, &ip, ipBuf, 256); _trackerManager->getBTTask()->getPeerManager()->addPeerInfoWithoutID(ipStr.c_str(), port); } } LOG_DEBUG("compact model"); } //set _nextUpdateTick _state = TS_OK; unsigned int connectedPeerCount = _trackerManager->getBTTask()->getPeerManager()->getConnectedPeerCount(); unsigned int maxPeerLinkCount = _trackerManager->getBTTask()->getPeerLinkMax(); if(connectedPeerCount >= maxPeerLinkCount || (connectedPeerCount > _total_peer/2) || _interval <= 2*60) { _nextUpdateTick = GetTickCount() + _interval*1000; } else { _nextUpdateTick = GetTickCount() + 2*60*1000; } //Set some flags if(_currentEvent == TE_START) { _startEventSend = true; }else if(_currentEvent == TE_COMPLETE) { _completeEventSend = true; } }std::string CTCPTracker::makeTrackerUrl(const char* event){/* std::string result = str(boost::format("%1%?info_hash=%2%&peer_id=%3%&port=%4%&uploaded=%5%&downloaded=%6%&left=%7%&event=%8%") % _url % urlEncode(_trackerManager->getBTTask()->getTorrentFile()->getInfoHash(), 20) % urlEncode((const unsigned char*)(_trackerManager->getBTTask()->getPeerID().c_str()), 20) % _trackerManager->getBTTask()->getAcceptor()->getPort() % _trackerManager->getBTTask()->getDownlaodCount() % _trackerManager->getBTTask()->getUploadCount() % _trackerManager->getBTTask()->getStorage()->getLeftCount() % event);*/ LOG_DEBUG("event="<<event); char result[1024]; sprintf(result, "%s?info_hash=%s&peer_id=%s&port=%u&compact=1&uploaded=%llu&downloaded=%llu&left=%llu&event=%s", _url.c_str(), urlEncode(_trackerManager->getBTTask()->getTorrentFile()->getInfoHash(), 20).c_str(), urlEncode((const unsigned char*)(_trackerManager->getBTTask()->getPeerID().c_str()), 20).c_str(), _trackerManager->getBTTask()->getAcceptor()->getPort(), _trackerManager->getBTTask()->getDownlaodCount(), _trackerManager->getBTTask()->getUploadCount(), _trackerManager->getBTTask()->getStorage()->getLeftCount(), event); LOG_DEBUG("TrackerUrl = " << result); return result; }const std::string& CTCPTracker::getStateStr(){ return _state_str;}unsigned int CTCPTracker::getSeedCount(){ return _complete_peer;}unsigned int CTCPTracker::getPeerCount(){ return _total_peer;}unsigned int CTCPTracker::getInterval(){ return _interval;}void CTCPTracker::setTrackerManager(ITrackerManager* trackerManager){ _trackerManager = trackerManager;}TTrackerEvent CTCPTracker::getCurrentEvent(){ if(!_startEventSend) { return TE_START; } if(_trackerManager->getBTTask()->getStorage()->finished() && _trackerManager->getBTTask()->getStorage()->getBanedCount() == 0 && !_completeEventSend) { return TE_COMPLETE; } return TE_NONE;}const char* CTCPTracker::event2Str(TTrackerEvent event){ switch(event) { case TE_START : return "started"; case TE_STOP : return "stopped"; case TE_COMPLETE : return "completed"; case TE_NONE : return ""; } return "";}unsigned int CTCPTracker::getNextUpdateTick(){ return _nextUpdateTick;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -