/** ** File ......... tSocket.cpp ** Published .... 2005-06-14 ** Author ....... grymse@alhem.net **/ /* Copyright (C) 2005 Anders Hedstrom 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. */ #ifdef _WIN32 #pragma warning(disable:4786) #endif #include #include "PeerHandler.h" #include "Session.h" #include "BString.h" #include "BTDictionary.h" #include "Exception.h" #include "Peer.h" #include "tSocket.h" #define DEB(x) int tSocket::m_next_id = 0; tSocket::tSocket(SocketHandler& h,const std::string& hash) :HttpGetSocket(h) ,m_hash(hash) ,m_gzip(false) { Session *p = static_cast(Handler()).GetSession(hash); if (p) { std::string announce = p -> GetAnnounceUrl("started"); std::string host; port_t port; Url(announce, host, port); if (host.size() && port) { PeerHandler& ref = static_cast(Handler()); m_filename = ref.GetTorrentDirectory() + "/" + hash + "/tracker." + Utility::l2string(++m_next_id); ref.mkpath( m_filename ); SetFilename(m_filename); SetConnectTimeout(30); Open(host, port); DEB(printf("Tracker host : %s\n", host.c_str());) DEB(printf("Tracker port : %d\n", port);) DEB(printf("Tracker URL : %s\n", announce.c_str());) } else SetCloseAndDelete(); } else SetCloseAndDelete(); } tSocket::~tSocket() { unlink(m_filename.c_str()); } void tSocket::OnDelete() { HttpGetSocket::OnDelete(); if (!Complete()) { DEB(printf("Tracker reply incomplete\n");) return; } Session *sess = static_cast(Handler()).GetSession(m_hash); if (!sess) { return; } if (m_gzip) { char cmd[1000]; DEB(printf("Tracker reply gzipped\n");) unlink(m_filename.substr(0, m_filename.size() - 3).c_str()); sprintf(cmd, "/usr/bin/gzip -d %s", m_filename.c_str()); system( cmd ); m_filename = m_filename.substr(0, m_filename.size() - 3); // remove .gz } DEB(printf("TrackerReply() in file '%s'\n",m_filename.c_str());) try { FILE *fil; if ((fil = fopen(m_filename.c_str(),"rb")) != NULL) { BString bstr; bstr.read_file(fil); fclose(fil); BTInteger *p = dynamic_cast(bstr.GetBTObject("interval")); if (p) { int interval = atoi(p -> GetValue().c_str()); DEB(printf("Tracker contact interval: %d\n",interval);) sess -> SetInterval( interval ); } BTList *l = dynamic_cast(bstr.GetBTObject("peers")); if (l) { DEB(printf(" peers found\n");) for (btobject_v::iterator it = l -> GetList().begin(); it != l -> GetList().end(); it++) { BTDictionary *p = dynamic_cast(*it); std::string ip; std::string id; int port = 0; if (p) { DEB(printf(" dictionary found\n");) for (btmap_t::iterator it = p -> GetMap().begin(); it != p -> GetMap().end(); it++) { std::string key = (*it).first; BTObject *p0 = (*it).second; if (key == "ip") { BTString *p = dynamic_cast(p0); if (p) ip = p -> GetValue(); } else if (key == "peer id") { BTString *p = dynamic_cast(p0); if (p) id = p -> GetValue(); } else if (key == "port") { BTInteger *p = dynamic_cast(p0); if (p) port = atoi(p -> GetValue().c_str()); } } } if (ip.size() && id.size() == 20 && port) { Peer *p = sess -> GetPeer(ip); if (!p) { Peer *p = new Peer(Handler(),m_hash,ip,id,port); sess -> AddPeer(p); } else { p -> SetPort(port); } } } } } } catch (const Exception& e) { DEB(printf("Exception when reading response from tracker: %s\n", e.GetText().c_str());) } } void tSocket::OnFirst() { HttpGetSocket::OnFirst(); DEB( printf("IsRequest: %s\n",IsRequest() ? "YES" : "NO"); if (IsRequest()) { printf(" Method: %s\n",GetMethod().c_str()); printf(" URL: %s\n",GetUrl().c_str()); printf(" Http version: %s\n",GetHttpVersion().c_str()); }) DEB( printf("IsResponse: %s\n",IsResponse() ? "YES" : "NO"); if (IsResponse()) { printf(" Http version: %s\n",GetHttpVersion().c_str()); printf(" Status: %s\n",GetStatus().c_str()); printf(" Status text: %s\n",GetStatusText().c_str()); }) } void tSocket::OnHeader(const std::string& key,const std::string& value) { HttpGetSocket::OnHeader(key,value); DEB(printf("%s: %s\n", key.c_str(), value.c_str());) if (!strcasecmp(key.c_str(), "content-encoding")) { if (!strcasecmp(value.c_str(), "gzip")) { m_filename += ".gz"; SetFilename(m_filename); m_gzip = true; } } }