📄 udptracker.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-26 20:09 */ #include <unistd.h>#include <netdb.h>#include <stdlib.h>#include <arpa/inet.h>#include "UDPTracker.h"#include "utils.h"#include "log.h"#pragma pack(push,1)typedef struct{ int64_t connection_id; unsigned int action_id; unsigned int transaction_id;} TConnectPacket;typedef struct{ int64_t connection_id; unsigned int action_id; unsigned int transaction_id; char info_hash[20]; char peer_id[20]; int64_t downloaded; int64_t left; int64_t uploaded; unsigned int event; unsigned int ip; unsigned int key; int num_want; unsigned short port; unsigned short extensions;} TAnnouncPacket;#pragma pack(pop)#define RECV_BUFFER_SIZE 8*1024CUDPTracker::CUDPTracker(){ _state = TS_INIT; memset(&_serverAddr, 0, sizeof(_serverAddr)); _completePeer = 0; _totalPeer = 0; _interval = 0; _nextUpdateTick = GetTickCount();}CUDPTracker::~CUDPTracker(){}void CUDPTracker::setTrackerManager(ITrackerManager* trackerManager){ _trackerManager = trackerManager;}bool CUDPTracker::isProtocolSupported(const char* protocolName){ if(strcmp(protocolName, "udp") == 0 || strcmp(protocolName, "UDP") == 0) { return true; } return false;}void CUDPTracker::setUrl(const char* url){ _url = url;}void CUDPTracker::update(){ if(_state == TS_INIT) { if(_serverAddr.sin_port == 0) { srand(GetTickCount()); //gethostbyname std::string host; std::string path; unsigned short port; if(!parseUrl(_url.c_str(), host, &port, path)) { _state = TS_ERROR; _stateStr = "Tracker URL error"; _interval = GetTickCount() + 60*60*1000; return; } struct hostent* hptr = gethostbyname(host.c_str()); if(hptr == NULL) { _state = TS_ERROR; _stateStr = "Can not find host : " + host; _interval = GetTickCount() + 60*1000; return; } _serverAddr.sin_family = AF_INET; _serverAddr.sin_addr.s_addr = *((in_addr_t *)hptr->h_addr_list[0]); _serverAddr.sin_port = htons(port); } CSocket::createUDPSocket(); CSocket::setReactor(_trackerManager->getBTTask()->getSocketReactor()); maskRead(true); sendConnectPacket(); _state = TS_CONNECTING; _nextUpdateTick = GetTickCount() + 15*1000; } if(_state == TS_ERROR || _state == TS_CONNECTING) { sendConnectPacket(); _state = TS_CONNECTING; _nextUpdateTick = GetTickCount() + 15*1000; } if(_state == TS_OK || _state == TS_REQUESTING) { sendAnnouncPacket(); }}void CUDPTracker::stop(){ CSocket::setReactor(NULL); CSocket::close();}TTrackerState CUDPTracker::getState(){ return _state;}const std::string& CUDPTracker::getStateStr(){ return _stateStr;}unsigned int CUDPTracker::getSeedCount(){ return _completePeer;}unsigned int CUDPTracker::getPeerCount(){ return _totalPeer;}unsigned int CUDPTracker::getInterval(){ return _interval;}unsigned int CUDPTracker::getNextUpdateTick(){ return _nextUpdateTick;}int CUDPTracker::handleRead(){ char* buf = new char[RECV_BUFFER_SIZE]; struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); socklen_t len = (socklen_t)sizeof(addr); int ret = recvfrom(getHandle(), buf, RECV_BUFFER_SIZE, 0, (struct sockaddr*)&addr, &len); LOG_DEBUG("recvfrom return "<<ret); if(addr.sin_addr.s_addr == _serverAddr.sin_addr.s_addr && ret > 8) { unsigned int actionID = *((unsigned int*)buf); actionID = ntohl(actionID); unsigned int transID = *((unsigned int*)(buf+4)); transID = ntohl(transID); if(transID == _transID) { processPkg(actionID, buf+8, ret - 8); } } delete[] buf; return 0;}int CUDPTracker::handleWrite(){ return 0;}void CUDPTracker::handleClose(){}void CUDPTracker::sendConnectPacket(){ _transID = rand() * GetTickCount(); TConnectPacket pkg; pkg.connection_id = 0x41727101980LL; pkg.connection_id = htonll(pkg.connection_id); pkg.action_id = 0; pkg.transaction_id = htonl(_transID); int ret = sendto(getHandle(), &pkg, sizeof(pkg), 0, (const struct sockaddr*)&_serverAddr, sizeof(_serverAddr)); LOG_DEBUG("sendto return "<<ret);}void CUDPTracker::sendAnnouncPacket(){ _transID = rand() * GetTickCount(); TAnnouncPacket pkg; pkg.connection_id = htonll(_connectionID); pkg.action_id = htonl(1); pkg.transaction_id = htonl(_transID); memcpy(pkg.info_hash, _trackerManager->getBTTask()->getTorrentFile()->getInfoHash(), 20); memcpy(pkg.peer_id, _trackerManager->getBTTask()->getPeerID().c_str(), 20); pkg.downloaded = htonl(_trackerManager->getBTTask()->getDownlaodCount()); pkg.left = htonl(_trackerManager->getBTTask()->getTorrentFile()->getTotalSize() - _trackerManager->getBTTask()->getDownlaodCount()); pkg.uploaded = htonl(_trackerManager->getBTTask()->getUploadCount()); pkg.event = htonl(getCurrentEvent()); pkg.ip = htonl(0); pkg.key = htonl(_transID * rand()); pkg.num_want = htonl(100); pkg.port = htons(_trackerManager->getBTTask()->getAcceptor()->getPort()); pkg.extensions = 0; sendto(getHandle(), &pkg, sizeof(pkg), 0, (const struct sockaddr*)&_serverAddr, sizeof(_serverAddr));}void CUDPTracker::processPkg(unsigned int actionID, char* data, size_t len){ LOG_DEBUG("recv pkg from UDP Tracker, actionID="<<actionID<<" len="<<len); if(actionID == 3) { _state = TS_ERROR; _stateStr.clear(); _stateStr.append((const char*)data, len); _nextUpdateTick = GetTickCount() + 15*1000; } if(actionID == 0) { _connectionID = *((int64_t*)data); _connectionID = ntohll(_connectionID); _state = TS_REQUESTING; sendAnnouncPacket(); _nextUpdateTick = GetTickCount() + 15*1000; } if(actionID == 1) { unsigned int interval = *((unsigned int*)data); interval = htonl(interval); unsigned int leechers = *((unsigned int*)(data+4)); leechers = htonl(leechers); unsigned int seeders = *((unsigned int*)(data+8)); seeders = htonl(seeders); _interval = interval; _totalPeer = leechers + seeders; _completePeer = seeders; LOG_DEBUG("UDP Tracker return, interval="<<interval<<" leechers="<<leechers<<" seeders="<<seeders); char* pbuf = NULL; for(unsigned int i=0; i<(len-12)/6; ++i) { pbuf = data + 12 + i*6; unsigned int ip = *((unsigned int*)pbuf); unsigned short port = *((unsigned short*)(pbuf+4)); port = ntohs(port); if(ip != 0 && port != 0) { char ipBuf[256]; std::string ipStr = inet_ntop(AF_INET, &ip, ipBuf, 256); LOG_DEBUG("UDP peer, ip="<<ipStr<<" port="<<port); _trackerManager->getBTTask()->getPeerManager()->addPeerInfoWithoutID(ipStr.c_str(), port); } } _state = TS_OK; unsigned int connectedPeerCount = _trackerManager->getBTTask()->getPeerManager()->getConnectedPeerCount(); unsigned int maxPeerLinkCount = _trackerManager->getBTTask()->getPeerLinkMax(); if(connectedPeerCount >= maxPeerLinkCount || (connectedPeerCount > _totalPeer/2) || _interval <= 2*60) { _nextUpdateTick = GetTickCount() + _interval*1000; } else { _nextUpdateTick = GetTickCount() + 2*60*1000; } //Set some flags if(_currentEvent == 2) { _startEventSend = true; }else if(_currentEvent == 1) { _completeEventSend = true; } }}int CUDPTracker::getCurrentEvent(){ if(!_startEventSend) { _currentEvent = 2; return 2; } if(_trackerManager->getBTTask()->getStorage()->finished() && _trackerManager->getBTTask()->getStorage()->getBanedCount() == 0 && !_completeEventSend) { _currentEvent = 1; return 1; } return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -