entry dht_tracker::state() const { entry ret(entry::dictionary_t); { entry nodes(entry::list_t); for (node_impl::iterator i(m_dht.begin()) , end(m_dht.end()); i != end; ++i) { std::string node; std::back_insert_iterator<std::string> out(node); write_endpoint(i->addr, out); nodes.list().push_back(entry(node)); } bucket_t cache; m_dht.replacement_cache(cache); for (bucket_t::iterator i(cache.begin()) , end(cache.end()); i != end; ++i) { std::string node; std::back_insert_iterator<std::string> out(node); write_endpoint(i->addr, out); nodes.list().push_back(entry(node)); } if (!nodes.list().empty()) ret["nodes"] = nodes; } ret["node-id"] = boost::lexical_cast<std::string>(m_dht.nid()); return ret; }
entry bdecode(const path &file) { ifstream fs(file, ifstream::binary); if(fs.is_open()) { fs.unsetf(ifstream::skipws); return libtorrent::bdecode(std::istream_iterator<char>(fs), std::istream_iterator<char>()); } else return entry(); }
void dht_tracker::send_packet(msg const& m) try { using libtorrent::bencode; using libtorrent::entry; entry e(entry::dictionary_t); TORRENT_ASSERT(!m.transaction_id.empty() || m.message_id == messages::error); e["t"] = m.transaction_id; static char const version_str[] = {'L', 'T' , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR}; e["v"] = std::string(version_str, version_str + 4); #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(dht_tracker) << time_now_string() << " SENDING [" << m.addr << "]:"; TORRENT_LOG(dht_tracker) << " transaction: " << m.transaction_id; #endif if (m.message_id == messages::error) { TORRENT_ASSERT(m.reply); e["y"] = "e"; entry error_list(entry::list_t); TORRENT_ASSERT(m.error_code > 200 && m.error_code <= 204); error_list.list().push_back(entry(m.error_code)); error_list.list().push_back(entry(m.error_msg)); e["e"] = error_list; #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(dht_tracker) << time_now_string() << " outgoing error: " << m.error_code << " " << m.error_msg; #endif } else if (m.reply) { e["y"] = "r"; e["r"] = entry(entry::dictionary_t); entry& r = e["r"]; r["id"] = std::string(m.id.begin(), m.id.end()); #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(dht_tracker) << time_now_string() << " reply: " << messages::ids[m.message_id]; #endif if (m.write_token.type() != entry::undefined_t) r["token"] = m.write_token; switch (m.message_id) { case messages::ping: break; case messages::find_node: { write_nodes_entry(r, m); break; } case messages::get_peers: { if (m.peers.empty()) { write_nodes_entry(r, m); } else { r["values"] = entry(entry::list_t); entry& p = r["values"]; std::string endpoint; for (msg::peers_t::const_iterator i = m.peers.begin() , end(m.peers.end()); i != end; ++i) { endpoint.resize(18); std::string::iterator out = endpoint.begin(); write_endpoint(*i, out); endpoint.resize(out - endpoint.begin()); p.list().push_back(entry(endpoint)); } #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size(); #endif } break; } case messages::announce_peer: break; break; } } else { e["y"] = "q"; e["a"] = entry(entry::dictionary_t); entry& a = e["a"]; a["id"] = std::string(m.id.begin(), m.id.end()); if (m.write_token.type() != entry::undefined_t) a["token"] = m.write_token; TORRENT_ASSERT(m.message_id <= messages::error); e["q"] = messages::ids[m.message_id]; #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(dht_tracker) << " query: " << messages::ids[m.message_id]; #endif switch (m.message_id) { case messages::find_node: { a["target"] = std::string(m.info_hash.begin(), m.info_hash.end()); #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(dht_tracker) << " target: " << boost::lexical_cast<std::string>(m.info_hash); #endif break; } case messages::get_peers: { a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end()); #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(dht_tracker) << " info_hash: " << boost::lexical_cast<std::string>(m.info_hash); #endif break; } case messages::announce_peer: a["port"] = m.port; a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end()); a["token"] = m.write_token; #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(dht_tracker) << " port: " << m.port << " info_hash: " << boost::lexical_cast<std::string>(m.info_hash); #endif break; default: break; } } m_send_buf.clear(); bencode(std::back_inserter(m_send_buf), e); error_code ec; m_socket.send_to(asio::buffer(&m_send_buf[0] , (int)m_send_buf.size()), m.addr, 0, ec); if (ec) return; #ifdef TORRENT_DHT_VERBOSE_LOGGING m_total_out_bytes += m_send_buf.size(); if (m.reply) { ++m_replies_sent[m.message_id]; m_replies_bytes_sent[m.message_id] += int(m_send_buf.size()); } else { m_queries_out_bytes += m_send_buf.size(); } TORRENT_LOG(dht_tracker) << e; #endif if (!m.piggy_backed_ping) return; msg pm; pm.reply = false; pm.piggy_backed_ping = false; pm.message_id = messages::ping; pm.transaction_id = m.ping_transaction_id; pm.id = m.id; pm.addr = m.addr; send_packet(pm); } catch (std::exception&) { // m_send may fail with "no route to host" // but it shouldn't throw since an error code // is passed in instead TORRENT_ASSERT(false); }