/** ** File ......... MyHandler.cpp ** Published .... 2004-04-20 **/ /* Copyright (C) 2004 grymse@alhem.net 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. */ //#include #include #include #include "MyHandler.h" MyHandler::MyHandler(const std::string& f) :MinderHandler() ,m_config(f) { } MyHandler::~MyHandler() { for (peer_m::iterator it = m_peers.begin(); it != m_peers.end(); it++) { std::string hash = (*it).first; peer_v& ref = (*it).second; for (peer_v::iterator it = ref.begin(); it != ref.end(); it++) { PEER *p = *it; delete p; } } } int MyHandler::GetInt(const std::string& path) { xmlNodePtr p = m_config.Find(m_config.GetRootElement(),path); if (p) { m_config.SetCurrent(p); std::string str = m_config.GetProperty("value"); return atoi(str.c_str()); } else { fprintf(stderr,"config path not found: %s\n",path.c_str()); } return 0; } std::string MyHandler::GetString(const std::string& path) { xmlNodePtr p = m_config.Find(m_config.GetRootElement(),path); if (p) { m_config.SetCurrent(p); std::string str = m_config.GetProperty("value"); return str; } fprintf(stderr,"config path not found: %s\n",path.c_str()); return ""; } bool MyHandler::GetBoolean(const std::string& path) { xmlNodePtr p = m_config.Find(m_config.GetRootElement(),path); std::string str; if (p) { m_config.SetCurrent(p); str = m_config.GetProperty("value"); if (str.size() && (str[0] == '1' || str[0] == 'y' || str[0] == 'Y' || str[0] == 't' || str[0] == 'T')) { return true; } return false; } fprintf(stderr,"config path not found: %s\n",path.c_str()); return false; } std::string MyHandler::escape(const std::string& in) { std::string out; for (size_t i = 0; i < in.size(); i++) { if (in[i] == '%') { out += in.substr(i,3); i += 2; } else { char slask[100]; sprintf(slask,"%02x",in[i]); out += '%'; out += slask; } } for (size_t i = 0; i < out.size(); i++) { if (out[i] >= 'a' && out[i] <= 'z') { out[i] = (char)out[i] - 32; } } return out; } MyHandler::PEER *MyHandler::reg_peer(const std::string& hash, const std::string& peer_id, const std::string& ip, port_t port) { std::string escaped_hash = escape(hash); std::string escaped_id = escape(peer_id); for (peer_v::iterator it = m_peers[escaped_hash].begin(); it != m_peers[escaped_hash].end(); it++) { PEER *p = *it; if (p -> escaped_peer_id == escaped_id) { p -> last_contact = time(NULL); return p; } } PEER *p = new PEER(escaped_id,ip,port); m_peers[escaped_hash].push_back(p); printf("Added new peer, id = %s\n",escaped_id.c_str()); return p; } //#define MIN(a,b) a < b ? a : b void MyHandler::CreatePeers(TcpSocket *sock,const std::string& hash,size_t numwant) { char slask[100]; size_t response_size = MIN((size_t)GetInt("server/max_give"),numwant); std::vector vec; size_t q = 0; for (peer_v::iterator it = m_peers[hash].begin(); it != m_peers[hash].end(); it++) { PEER *p = *it; vec.push_back(p); q++; } while (response_size && q) { size_t nr = random() % q; PEER *p = vec[nr]; // dictionary sock -> Send("d"); sock -> Send("2:ip"); // ip sprintf(slask,"%d:%s",p -> ip.size(),p -> ip.c_str()); sock -> Send(slask); sock -> Send("7:peer id" "20:"); // peer id sock -> SendBuf( (char *)p -> peer_id,20); sock -> Send("4:port"); // port sprintf(slask,"i%de",p -> port); sock -> Send(slask); // end dictionary sock -> Send("e"); vec[nr] = vec[q - 1]; q--; response_size--; } } void MyHandler::SendList() { // send changes to peer list for (peer_m::iterator it = m_peers.begin(); it != m_peers.end(); it++) { std::string hash = (*it).first; peer_v& ref = (*it).second; for (peer_v::iterator it = ref.begin(); it != ref.end(); it++) { PEER *p = *it; if (p -> updated) { std::string msg = p -> stopped ? "delete" : "update"; msg += ":" + hash; msg += ":" + p -> escaped_peer_id; msg += ":" + p -> ip; msg += ":" + Utility::l2string(p -> port); msg += ":" + Utility::bigint2string(p -> uploaded); msg += ":" + Utility::bigint2string(p -> downloaded); msg += ":" + Utility::bigint2string(p -> left); SendMessage(Utility::base64(msg)); p -> updated = false; } } } // clear peer list from stopped peers bool repeat; do { repeat = false; for (peer_m::iterator it = m_peers.begin(); it != m_peers.end(); it++) { std::string hash = (*it).first; peer_v& ref = (*it).second; for (peer_v::iterator it = ref.begin(); it != ref.end(); it++) { PEER *p = *it; if (p -> stopped && !p -> updated) { delete p; ref.erase(it); repeat = true; break; } } } } while (repeat); } void MyHandler::CheckDropped() { time_t tnow = time(NULL); for (peer_m::iterator it = m_peers.begin(); it != m_peers.end(); it++) { std::string hash = (*it).first; peer_v& ref = (*it).second; for (peer_v::iterator it = ref.begin(); it != ref.end(); it++) { PEER *p = *it; if (tnow - p -> last_contact > GetInt("server/timeout_downloaders_interval")) { p -> stop(); } } } } void MyHandler::SendInit(MyMinionSocket *ps) { // send changes to peer list for (peer_m::iterator it = m_peers.begin(); it != m_peers.end(); it++) { std::string hash = (*it).first; peer_v& ref = (*it).second; for (peer_v::iterator it = ref.begin(); it != ref.end(); it++) { PEER *p = *it; if (!p -> stopped) { Uid ruid(ps -> GetRemoteId()); std::string msg = p -> stopped ? "delete" : "update"; msg += ":" + hash; msg += ":" + p -> escaped_peer_id; msg += ":" + p -> ip; msg += ":" + Utility::l2string(p -> port); msg += ":" + Utility::bigint2string(p -> uploaded); msg += ":" + Utility::bigint2string(p -> downloaded); msg += ":" + Utility::bigint2string(p -> left); // SendMessage(Utility::base64(msg)); memcpy(GetKey_m2minion() + 8,ruid.GetBuf(),16); ps -> Send( ps -> encrypt(GetKey_m2minion(),msg) + "\n" ); } } } } size_t MyHandler::MapSize() { size_t q = 0; for (peer_m::iterator it = m_peers.begin(); it != m_peers.end(); it++) { q++; } return q; }