time_duration rpc_manager::tick() { INVARIANT_CHECK; static const int short_timeout = 1; static const int timeout = 15; // look for observers that have timed out if (m_transactions.empty()) return seconds(short_timeout); std::vector<observer_ptr> timeouts; std::vector<observer_ptr> short_timeouts; time_duration ret = seconds(short_timeout); time_point now = aux::time_now(); for (transactions_t::iterator i = m_transactions.begin(); i != m_transactions.end();) { observer_ptr o = i->second; time_duration diff = now - o->sent(); if (diff >= seconds(timeout)) { #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "[%p] timing out transaction id: %d from: %s" , static_cast<void*>(o->algorithm()), o->transaction_id() , print_endpoint(o->target_ep()).c_str()); #endif m_transactions.erase(i++); timeouts.push_back(o); continue; } // don't call short_timeout() again if we've // already called it once if (diff >= seconds(short_timeout) && !o->has_short_timeout()) { #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "[%p] short-timing out transaction id: %d from: %s" , static_cast<void*>(o->algorithm()), o->transaction_id() , print_endpoint(o->target_ep()).c_str()); #endif ++i; short_timeouts.push_back(o); continue; } ret = std::min(seconds(timeout) - diff, ret); ++i; } std::for_each(timeouts.begin(), timeouts.end(), std::bind(&observer::timeout, _1)); std::for_each(short_timeouts.begin(), short_timeouts.end(), std::bind(&observer::short_timeout, _1)); return (std::max)(ret, duration_cast<time_duration>(milliseconds(200))); }
void find_data::done() { m_done = true; #ifndef TORRENT_DISABLE_LOGGING auto logger = get_node().observer(); if (logger != nullptr) { logger->log(dht_logger::traversal, "[%u] %s DONE" , id(), name()); } #endif std::vector<std::pair<node_entry, std::string>> results; int num_results = m_node.m_table.bucket_size(); for (std::vector<observer_ptr>::iterator i = m_results.begin() , end(m_results.end()); i != end && num_results > 0; ++i) { observer_ptr const& o = *i; if ((o->flags & observer::flag_alive) == 0) { #ifndef TORRENT_DISABLE_LOGGING if (logger != nullptr && logger->should_log(dht_logger::traversal)) { logger->log(dht_logger::traversal, "[%u] not alive: %s" , id(), print_endpoint(o->target_ep()).c_str()); } #endif continue; } auto j = m_write_tokens.find(o->id()); if (j == m_write_tokens.end()) { #ifndef TORRENT_DISABLE_LOGGING if (logger != nullptr && logger->should_log(dht_logger::traversal)) { logger->log(dht_logger::traversal, "[%u] no write token: %s" , id(), print_endpoint(o->target_ep()).c_str()); } #endif continue; } results.push_back(std::make_pair(node_entry(o->id(), o->target_ep()), j->second)); #ifndef TORRENT_DISABLE_LOGGING if (logger != nullptr && logger->should_log(dht_logger::traversal)) { logger->log(dht_logger::traversal, "[%u] %s" , id(), print_endpoint(o->target_ep()).c_str()); } #endif --num_results; } if (m_nodes_callback) m_nodes_callback(results); traversal_algorithm::done(); }
char *print_connection(connection_t *connection) { char *result = NULL; char *connection_info = NULL; char *request_endpoint_info = NULL; char *response_endpoint_info = NULL; int success; success = asprintf( &connection_info, "%s\n | %-39s |\n%s\n | %-39s |\n%s\n | %-18s | %-18s |\n%s\n | %-18s | %-18s |\n%s\n", get_hdr_line(0), "Connection by Call-ID", get_line(0), connection->call_id, get_hdr_line(1), "Request IP", "Response IP", get_line(1), connection->request_endpoint != NULL ? *(connection->request_endpoint_ip) : "none", connection->response_endpoint != NULL ? *(connection->response_endpoint_ip) : "none", get_line(0) ); if (success == -1) { ERR("asprintf failed to allocate memory\n"); return NULL; } request_endpoint_info = print_endpoint(connection->request_endpoint, "Request endpoint"); response_endpoint_info = print_endpoint(connection->response_endpoint, "Response endpoint"); success = asprintf( &result, "%s\n%s%s\n\n\n", connection_info, request_endpoint_info, response_endpoint_info ); if (connection_info != NULL) free(connection_info); if (request_endpoint_info != NULL) free(request_endpoint_info); if (response_endpoint_info != NULL) free(response_endpoint_info); if (success == -1) { ERR("asprintf failed to allocate memory\n"); return NULL; } return result; }
PRIVATE void print_sigmgr(struct proc *pp) { endpoint_t sig_mgr, bak_sig_mgr; sig_mgr = priv(pp)->s_sig_mgr; bak_sig_mgr = priv(pp)->s_bak_sig_mgr; printf("sigmgr "); print_endpoint(sig_mgr); if(bak_sig_mgr != NONE) { printf(" / "); print_endpoint(bak_sig_mgr); } }
static void print_sigmgr(struct proc *pp) { endpoint_t sig_mgr, bak_sig_mgr; sig_mgr = priv(pp) ? priv(pp)->s_sig_mgr : NONE; bak_sig_mgr = priv(pp) ? priv(pp)->s_bak_sig_mgr : NONE; if(sig_mgr == NONE) { printf("no sigmgr"); return; } printf("sigmgr "); print_endpoint(sig_mgr); if(bak_sig_mgr != NONE) { printf(" / "); print_endpoint(bak_sig_mgr); } }
std::string listen_failed_alert::message() const { char ret[200]; snprintf(ret, sizeof(ret), "listening on %s failed: %s" , print_endpoint(endpoint).c_str(), error.message().c_str()); return ret; }
void print_proc(struct proc *pp) { endpoint_t dep; printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cpu %2d " "pdbr 0x%lx rts %s misc %s sched %s ", proc_nr(pp), pp->p_name, pp->p_endpoint, pp->p_priority, pp->p_user_time, pp->p_sys_time, ex64hi(pp->p_cycles), ex64lo(pp->p_cycles), pp->p_cpu, #if defined(__i386__) pp->p_seg.p_cr3, #elif defined(__arm__) pp->p_seg.p_ttbr, #endif rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags), schedulerstr(pp->p_scheduler)); print_sigmgr(pp); dep = P_BLOCKEDON(pp); if(dep != NONE) { printf(" blocked on: "); print_endpoint(dep); } printf("\n"); }
std::string listen_succeeded_alert::message() const { char ret[200]; snprintf(ret, sizeof(ret), "successfully listening on [%s] %s" , sock_type_str[sock_type], print_endpoint(endpoint).c_str()); return ret; }
std::string peer_log_alert::message() const { static char const* mode[] = { "<==", "==>", "<<<", ">>>", "***" }; return torrent_alert::message() + " [" + print_endpoint(ip) + "] " + mode[direction] + " " + event_type + " [ " + msg() + " ]"; }
static void print_interface(openusb_devid_t devid, int cfgidx, int ifcidx,int alt, struct usb_interface_desc *intf) { int i; int ret; printf(" Interface: %d\n", ifcidx); printf(" bInterfaceNumber: %d\n", intf->bInterfaceNumber); printf(" bAlternateSetting: %d\n", intf->bAlternateSetting); printf(" bNumEndpoints: %d\n", intf->bNumEndpoints); printf(" bInterfaceClass: %02x\n", intf->bInterfaceClass); printf(" bInterfaceSubClass: %02x\n", intf->bInterfaceSubClass); printf(" bInterfaceProtocol: %02x\n", intf->bInterfaceProtocol); printf(" iInterface: %d\n", intf->iInterface); printf("\n"); for (i = 0; i < intf->bNumEndpoints; i++) { struct usb_endpoint_desc ep; ret = openusb_parse_endpoint_desc(libhandle,devid,NULL,0, cfgidx,ifcidx,alt,i,&ep); if(ret != 0) { printf("parse endpoint desc fail, ret = %d %s\n", ret, openusb_strerror(ret)); return; } print_endpoint(&ep); } }
std::string incoming_connection_alert::message() const { char msg[600]; error_code ec; snprintf(msg, sizeof(msg), "incoming connection from %s (%s)" , print_endpoint(ip).c_str(), socket_type_str[socket_type]); return msg; }
bool tracker_manager::incoming_packet(udp::endpoint const& ep , span<char const> const buf) { TORRENT_ASSERT(is_single_thread()); // ignore packets smaller than 8 bytes if (buf.size() < 8) { #ifndef TORRENT_DISABLE_LOGGING if (m_ses.should_log()) { m_ses.session_log("incoming packet from %s, not a UDP tracker message " "(%d Bytes)", print_endpoint(ep).c_str(), int(buf.size())); } #endif return false; } // the first word is the action, if it's not [0, 3] // it's not a valid udp tracker response span<const char> ptr = buf; std::uint32_t const action = aux::read_uint32(ptr); if (action > 3) return false; std::uint32_t const transaction = aux::read_uint32(ptr); auto const i = m_udp_conns.find(transaction); if (i == m_udp_conns.end()) { #ifndef TORRENT_DISABLE_LOGGING if (m_ses.should_log()) { m_ses.session_log("incoming UDP tracker packet from %s has invalid " "transaction ID (%x)", print_endpoint(ep).c_str() , transaction); } #endif return false; } std::shared_ptr<udp_tracker_connection> const p = i->second; // on_receive() may remove the tracker connection from the list return p->on_receive(ep, buf); }
std::string listen_succeeded_alert::message() const { static char const* type_str[] = { "TCP", "TCP/SSL", "UDP" }; char ret[200]; snprintf(ret, sizeof(ret), "successfully listening on [%s] %s" , type_str[sock_type], print_endpoint(endpoint).c_str()); return ret; }
void traversal_algorithm::done() { #ifndef TORRENT_DISABLE_LOGGING int results_target = m_node.m_table.bucket_size(); int closest_target = 160; #endif for (auto const& o : m_results) { if ((o->flags & (observer::flag_queried | observer::flag_failed)) == observer::flag_queried) { // set the done flag on any outstanding queries to prevent them from // calling finished() or failed() after we've already declared the traversal // done o->flags |= observer::flag_done; } #ifndef TORRENT_DISABLE_LOGGING dht_observer* logger = get_node().observer(); if (results_target > 0 && (o->flags & observer::flag_alive) && logger != nullptr && logger->should_log(dht_logger::traversal)) { TORRENT_ASSERT(o->flags & observer::flag_queried); char hex_id[41]; aux::to_hex(o->id(), hex_id); logger->log(dht_logger::traversal , "[%p] id: %s distance: %d addr: %s" , static_cast<void*>(this), hex_id, closest_target , print_endpoint(o->target_ep()).c_str()); --results_target; int dist = distance_exp(m_target, o->id()); if (dist < closest_target) closest_target = dist; } #endif } #ifndef TORRENT_DISABLE_LOGGING if (get_node().observer() != nullptr) { get_node().observer()->log(dht_logger::traversal , "[%p] COMPLETED distance: %d type: %s" , static_cast<void*>(this), closest_target, name()); } #endif // delete all our references to the observer objects so // they will in turn release the traversal algorithm m_results.clear(); m_invoke_count = 0; }
static void print_altsetting(struct usb_interface_descriptor *interface) { int i; edit_printf(" bInterfaceNumber: %d\r\n", interface->bInterfaceNumber); edit_printf(" bAlternateSetting: %d\r\n", interface->bAlternateSetting); edit_printf(" bNumEndpoints: %d\r\n", interface->bNumEndpoints); edit_printf(" bInterfaceClass: %d\r\n", interface->bInterfaceClass); edit_printf(" bInterfaceSubClass: %d\r\n", interface->bInterfaceSubClass); edit_printf(" bInterfaceProtocol: %d\r\n", interface->bInterfaceProtocol); edit_printf(" iInterface: %d\r\n", interface->iInterface); for (i = 0; i < interface->bNumEndpoints; i++) print_endpoint(&interface->endpoint[i]); }
std::string dht_outgoing_get_peers_alert::message() const { char msg[600]; char obf[70]; obf[0] = '\0'; if (obfuscated_info_hash != info_hash) { snprintf(obf, sizeof(obf), " [obfuscated: %s]" , to_hex(obfuscated_info_hash.to_string()).c_str()); } snprintf(msg, sizeof(msg), "outgoing dht get_peers : %s%s -> %s" , to_hex(info_hash.to_string()).c_str() , obf , print_endpoint(ip).c_str()); return msg; }
bool rpc_manager::invoke(entry& e, udp::endpoint target_addr , observer_ptr o) { INVARIANT_CHECK; if (m_destructing) return false; e["y"] = "q"; entry& a = e["a"]; add_our_id(a); std::string transaction_id; transaction_id.resize(2); char* out = &transaction_id[0]; int tid = (random() ^ (random() << 5)) & 0xffff; io::write_uint16(tid, out); e["t"] = transaction_id; // When a DHT node enters the read-only state, in each outgoing query message, // places a 'ro' key in the top-level message dictionary and sets its value to 1. if (m_settings.read_only) e["ro"] = 1; node& n = o->algorithm()->get_node(); if (!n.native_address(o->target_addr())) { a["want"].list().push_back(entry(n.protocol_family_name())); } o->set_target(target_addr); o->set_transaction_id(tid); #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "[%p] invoking %s -> %s" , static_cast<void*>(o->algorithm()), e["q"].string().c_str() , print_endpoint(target_addr).c_str()); #endif if (m_sock->send_packet(e, target_addr)) { m_transactions.insert(std::make_pair(tid, o)); #if TORRENT_USE_ASSERTS o->m_was_sent = true; #endif return true; } return false; }
std::string dht_pkt_alert::message() const { bdecode_node print; error_code ec; // ignore errors here. This is best-effort. It may be a broken encoding // but at least we'll print the valid parts bdecode(pkt_buf(), pkt_buf() + pkt_size(), print, ec, NULL, 100, 100); std::string msg = print_entry(print, true); char const* prefix[2] = { "<==", "==>"}; char buf[1024]; snprintf(buf, sizeof(buf), "%s [%s] %s", prefix[dir] , print_endpoint(node).c_str(), msg.c_str()); return buf; }
std::string listen_failed_alert::message() const { static char const* op_str[] = { "parse_addr", "open", "bind", "listen", "get_socket_name", "accept", "enum_if", "bind_to_device" }; char ret[300]; snprintf(ret, sizeof(ret), "listening on %s (device: %s) failed: [%s] [%s] %s" , print_endpoint(endpoint).c_str() , listen_interface() , op_str[operation] , sock_type_str[sock_type] , convert_from_native(error.message()).c_str()); return ret; }
void rpc_manager::unreachable(udp::endpoint const& ep) { #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "PORT_UNREACHABLE [ ip: %s ]" , print_endpoint(ep).c_str()); #endif for (transactions_t::iterator i = m_transactions.begin(); i != m_transactions.end();) { TORRENT_ASSERT(i->second); observer_ptr const& o = i->second; if (o->target_ep() != ep) { ++i; continue; } observer_ptr ptr = i->second; i = m_transactions.erase(i); #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "found transaction [ tid: %d ]" , int(ptr->transaction_id())); #endif ptr->timeout(); break; } }
std::string listen_failed_alert::message() const { static char const* op_str[] = { "parse_addr", "open", "bind", "listen", "get_peer_name", "accept" }; static char const* type_str[] = { "TCP", "TCP/SSL", "UDP", "I2P", "Socks5" }; char ret[250]; snprintf(ret, sizeof(ret), "listening on %s failed: [%s] [%s] %s" , print_endpoint(endpoint).c_str() , op_str[operation] , type_str[sock_type] , convert_from_native(error.message()).c_str()); return ret; }
bool rpc_manager::invoke(entry& e, udp::endpoint target_addr , observer_ptr o) { INVARIANT_CHECK; if (m_destructing) return false; e["y"] = "q"; entry& a = e["a"]; add_our_id(a); std::string transaction_id; transaction_id.resize(2); char* out = &transaction_id[0]; int tid = (random() ^ (random() << 5)) & 0xffff; io::write_uint16(tid, out); e["t"] = transaction_id; o->set_target(target_addr); o->set_transaction_id(tid); #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "[%p] invoking %s -> %s" , static_cast<void*>(o->algorithm()), e["q"].string().c_str() , print_endpoint(target_addr).c_str()); #endif if (m_sock->send_packet(e, target_addr, 1)) { m_transactions.insert(std::make_pair(tid,o)); #if TORRENT_USE_ASSERTS o->m_was_sent = true; #endif return true; } return false; }
PUBLIC void print_proc(struct proc *pp) { struct proc *depproc = NULL; endpoint_t dep; printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cpu %2d " "cr3 0x%lx rts %s misc %s sched %s ", proc_nr(pp), pp->p_name, pp->p_endpoint, pp->p_priority, pp->p_user_time, pp->p_sys_time, ex64hi(pp->p_cycles), ex64lo(pp->p_cycles), pp->p_cpu, pp->p_seg.p_cr3, rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags), schedulerstr(pp->p_scheduler)); print_sigmgr(pp); dep = P_BLOCKEDON(pp); if(dep != NONE) { printf(" blocked on: "); print_endpoint(dep); } printf("\n"); }
bool rpc_manager::incoming(msg const& m, node_id* id , libtorrent::dht_settings const& settings) { INVARIANT_CHECK; if (m_destructing) return false; // we only deal with replies and errors, not queries TORRENT_ASSERT(m.message.dict_find_string_value("y") == "r" || m.message.dict_find_string_value("y") == "e"); // if we don't have the transaction id in our // request list, ignore the packet std::string transaction_id = m.message.dict_find_string_value("t"); if (transaction_id.empty()) return false; std::string::const_iterator i = transaction_id.begin(); int tid = transaction_id.size() != 2 ? -1 : io::read_uint16(i); observer_ptr o; std::pair<transactions_t::iterator, transactions_t::iterator> range = m_transactions.equal_range(tid); for (transactions_t::iterator i = range.first; i != range.second; ++i) { if (m.addr.address() != i->second->target_addr()) continue; o = i->second; i = m_transactions.erase(i); break; } if (!o) { #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "reply with unknown transaction id size: %d from %s" , int(transaction_id.size()), print_endpoint(m.addr).c_str()); #endif // this isn't necessarily because the other end is doing // something wrong. This can also happen when we restart // the node, and we prematurely abort all outstanding // requests. Also, this opens up a potential magnification // attack. // entry e; // incoming_error(e, "invalid transaction id"); // m_sock->send_packet(e, m.addr, 0); return false; } time_point now = clock_type::now(); #ifndef TORRENT_DISABLE_LOGGING std::ofstream reply_stats("round_trip_ms.log", std::ios::app); reply_stats << m.addr << "\t" << total_milliseconds(now - o->sent()) << std::endl; #endif bdecode_node ret_ent = m.message.dict_find_dict("r"); if (!ret_ent) { // it may be an error ret_ent = m.message.dict_find("e"); o->timeout(); if (!ret_ent) { entry e; incoming_error(e, "missing 'r' key"); m_sock->send_packet(e, m.addr, 0); } return false; } bdecode_node node_id_ent = ret_ent.dict_find_string("id"); if (!node_id_ent || node_id_ent.string_length() != 20) { o->timeout(); entry e; incoming_error(e, "missing 'id' key"); m_sock->send_packet(e, m.addr, 0); return false; } node_id nid = node_id(node_id_ent.string_ptr()); if (settings.enforce_node_id && !verify_id(nid, m.addr.address())) { o->timeout(); entry e; incoming_error(e, "invalid node ID"); m_sock->send_packet(e, m.addr, 0); return false; } #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "[%p] reply with transaction id: %d from %s" , o->algorithm(), int(transaction_id.size()) , print_endpoint(m.addr).c_str()); #endif o->reply(m); *id = nid; int rtt = int(total_milliseconds(now - o->sent())); // we found an observer for this reply, hence the node is not spoofing // add it to the routing table return m_table.node_seen(*id, m.addr, rtt); }
std::string peer_alert::message() const { error_code ec; return torrent_alert::message() + " peer (" + print_endpoint(ip) + ", " + identify_client(pid) + ")"; }
bool rpc_manager::incoming(msg const& m, node_id* id) { INVARIANT_CHECK; if (m_destructing) return false; // we only deal with replies and errors, not queries TORRENT_ASSERT(m.message.dict_find_string_value("y") == "r" || m.message.dict_find_string_value("y") == "e"); // if we don't have the transaction id in our // request list, ignore the packet std::string transaction_id = m.message.dict_find_string_value("t"); if (transaction_id.empty()) return false; std::string::const_iterator ptr = transaction_id.begin(); int tid = transaction_id.size() != 2 ? -1 : io::read_uint16(ptr); observer_ptr o; std::pair<transactions_t::iterator, transactions_t::iterator> range = m_transactions.equal_range(tid); for (transactions_t::iterator i = range.first; i != range.second; ++i) { if (m.addr.address() != i->second->target_addr()) continue; o = i->second; i = m_transactions.erase(i); break; } if (!o) { #ifndef TORRENT_DISABLE_LOGGING if (m_table.native_endpoint(m.addr)) { m_log->log(dht_logger::rpc_manager, "reply with unknown transaction id size: %d from %s" , int(transaction_id.size()), print_endpoint(m.addr).c_str()); } #endif // this isn't necessarily because the other end is doing // something wrong. This can also happen when we restart // the node, and we prematurely abort all outstanding // requests. Also, this opens up a potential magnification // attack. // entry e; // incoming_error(e, "invalid transaction id"); // m_sock->send_packet(e, m.addr); return false; } time_point now = clock_type::now(); #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "round trip time(ms): %" PRId64 " from %s" , total_milliseconds(now - o->sent()), print_endpoint(m.addr).c_str()); #endif if (m.message.dict_find_string_value("y") == "e") { // It's an error. #ifndef TORRENT_DISABLE_LOGGING bdecode_node err = m.message.dict_find_list("e"); if (err && err.list_size() >= 2 && err.list_at(0).type() == bdecode_node::int_t && err.list_at(1).type() == bdecode_node::string_t) { m_log->log(dht_logger::rpc_manager, "reply with error from %s: (%" PRId64 ") %s" , print_endpoint(m.addr).c_str() , err.list_int_value_at(0) , err.list_string_value_at(1).c_str()); } else { m_log->log(dht_logger::rpc_manager, "reply with (malformed) error from %s" , print_endpoint(m.addr).c_str()); } #endif // Logically, we should call o->reply(m) since we get a reply. // a reply could be "response" or "error", here the reply is an "error". // if the reply is an "error", basically the observer could/will // do nothing with it, especially when observer::reply() is intended to // handle a "response", not an "error". // A "response" should somehow call algorithm->finished(), and an error/timeout // should call algorithm->failed(). From this point of view, // we should call o->timeout() instead of o->reply(m) because o->reply() // will call algorithm->finished(). o->timeout(); return false; } bdecode_node ret_ent = m.message.dict_find_dict("r"); if (!ret_ent) { o->timeout(); return false; } bdecode_node node_id_ent = ret_ent.dict_find_string("id"); if (!node_id_ent || node_id_ent.string_length() != 20) { o->timeout(); return false; } node_id nid = node_id(node_id_ent.string_ptr()); if (m_settings.enforce_node_id && !verify_id(nid, m.addr.address())) { o->timeout(); return false; } #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::rpc_manager, "[%p] reply with transaction id: %d from %s" , static_cast<void*>(o->algorithm()), int(transaction_id.size()) , print_endpoint(m.addr).c_str()); #endif o->reply(m); *id = nid; int rtt = int(total_milliseconds(now - o->sent())); // we found an observer for this reply, hence the node is not spoofing // add it to the routing table return m_table.node_seen(*id, m.addr, rtt); }
void error_logger::handle_alert(alert const* a) { if (m_file == NULL) return; time_t now = time(NULL); char timestamp[256]; strncpy(timestamp, ctime(&now), sizeof(timestamp)); for (int i = 0; i < sizeof(timestamp); ++i) { if (timestamp[i] != '\n' && timestamp[i] != '\r') continue; timestamp[i] = '\0'; break; } switch (a->type()) { case peer_error_alert::alert_type: { peer_error_alert const* pe = alert_cast<peer_error_alert>(a); #ifdef TORRENT_USE_OPENSSL // unknown protocol if (pe->error != error_code(336027900, boost::asio::error::get_ssl_category())) #endif { fprintf(m_file, "%s\terror [%s] (%s:%d) %s\n", timestamp , print_endpoint(pe->ip).c_str(), pe->error.category().name() , pe->error.value(), pe->error.message().c_str()); } break; } case peer_disconnected_alert::alert_type: { peer_disconnected_alert const* pd = alert_cast<peer_disconnected_alert>(a); if (pd && pd->error != boost::system::errc::connection_reset && pd->error != boost::system::errc::connection_aborted && pd->error != boost::system::errc::connection_refused && pd->error != boost::system::errc::timed_out && pd->error != boost::asio::error::eof && pd->error != boost::asio::error::host_unreachable && pd->error != boost::asio::error::network_unreachable && pd->error != boost::asio::error::broken_pipe #ifdef TORRENT_USE_OPENSSL // unknown protocol && pd->error != error_code(336027900, boost::asio::error::get_ssl_category()) #endif && pd->error != error_code(libtorrent::errors::self_connection) && pd->error != error_code(libtorrent::errors::torrent_removed) && pd->error != error_code(libtorrent::errors::torrent_aborted) && pd->error != error_code(libtorrent::errors::stopping_torrent) && pd->error != error_code(libtorrent::errors::session_closing) && pd->error != error_code(libtorrent::errors::duplicate_peer_id) && pd->error != error_code(libtorrent::errors::timed_out) && pd->error != error_code(libtorrent::errors::timed_out_no_handshake) && pd->error != error_code(libtorrent::errors::upload_upload_connection)) fprintf(m_file, "%s\tdisconnect [%s][%s] (%s:%d) %s\n", timestamp , print_endpoint(pd->ip).c_str(), operation_name(pd->operation) , pd->error.category().name(), pd->error.value(), pd->error.message().c_str()); break; } case save_resume_data_failed_alert::alert_type: { save_resume_data_failed_alert const* rs= alert_cast<save_resume_data_failed_alert>(a); if (rs) fprintf(m_file, "%s\tsave-resume-failed (%s:%d) %s\n", timestamp , rs->error.category().name(), rs->error.value() , rs->message().c_str()); } case torrent_delete_failed_alert::alert_type: { torrent_delete_failed_alert const* td = alert_cast<torrent_delete_failed_alert>(a); if (td) fprintf(m_file, "%s\tstorage-delete-failed (%s:%d) %s\n", timestamp , td->error.category().name(), td->error.value() , td->message().c_str()); } case storage_moved_failed_alert::alert_type: { storage_moved_failed_alert const* sm = alert_cast<storage_moved_failed_alert>(a); if (sm) fprintf(m_file, "%s\tstorage-move-failed (%s:%d) %s\n", timestamp , sm->error.category().name(), sm->error.value() , sm->message().c_str()); } case file_rename_failed_alert::alert_type: { file_rename_failed_alert const* rn = alert_cast<file_rename_failed_alert>(a); if (rn) fprintf(m_file, "%s\tfile-rename-failed (%s:%d) %s\n", timestamp , rn->error.category().name(), rn->error.value() , rn->message().c_str()); } case torrent_error_alert::alert_type: { torrent_error_alert const* te = alert_cast<torrent_error_alert>(a); if (te) fprintf(m_file, "%s\ttorrent-error (%s:%d) %s\n", timestamp , te->error.category().name(), te->error.value() , te->message().c_str()); } case hash_failed_alert::alert_type: { hash_failed_alert const* hf = alert_cast<hash_failed_alert>(a); if (hf) fprintf(m_file, "%s\thash-failed %s\n", timestamp , hf->message().c_str()); } case file_error_alert::alert_type: { file_error_alert const* fe = alert_cast<file_error_alert>(a); if (fe) fprintf(m_file, "%s\tfile-error (%s:%d) %s\n", timestamp , fe->error.category().name(), fe->error.value() , fe->message().c_str()); } case metadata_failed_alert::alert_type: { metadata_failed_alert const* mf = alert_cast<metadata_failed_alert>(a); if (mf) fprintf(m_file, "%s\tmetadata-error (%s:%d) %s\n", timestamp , mf->error.category().name(), mf->error.value() , mf->message().c_str()); } case udp_error_alert::alert_type: { udp_error_alert const* ue = alert_cast<udp_error_alert>(a); if (ue) fprintf(m_file, "%s\tudp-error (%s:%d) %s %s\n", timestamp , ue->error.category().name(), ue->error.value() , print_endpoint(ue->endpoint).c_str() , ue->error.message().c_str()); } case listen_failed_alert::alert_type: { listen_failed_alert const* lf = alert_cast<listen_failed_alert>(a); if (lf) fprintf(m_file, "%s\tlisten-error (%s:%d) %s\n", timestamp , lf->error.category().name(), lf->error.value() , lf->message().c_str()); } case rss_alert::alert_type: { rss_alert const* ra = alert_cast<rss_alert>(a); if (ra && ra->state == rss_alert::state_error) fprintf(m_file, "%s\trss-error (%s:%d) %s %s\n", timestamp , ra->error.category().name(), ra->error.value() , ra->error.message().c_str() , ra->url.c_str()); } case invalid_request_alert::alert_type: { invalid_request_alert const* ira = alert_cast<invalid_request_alert>(a); if (ira) fprintf(m_file, "%s\tinvalid-request %s\n", timestamp , ira->message().c_str()); } case mmap_cache_alert::alert_type: { mmap_cache_alert const* ma = alert_cast<mmap_cache_alert>(a); if (ma) fprintf(m_file, "%s\tmmap-cache-error (%s:%d )%s\n", timestamp , ma->error.category().name(), ma->error.value() , ma->message().c_str()); } } }
void traversal_algorithm::add_entry(node_id const& id , udp::endpoint const& addr, unsigned char const flags) { TORRENT_ASSERT(m_node.m_rpc.allocation_size() >= sizeof(find_data_observer)); auto o = new_observer(addr, id); if (!o) { #ifndef TORRENT_DISABLE_LOGGING if (get_node().observer() != nullptr) { get_node().observer()->log(dht_logger::traversal, "[%p] failed to allocate memory or observer. aborting!" , static_cast<void*>(this)); } #endif done(); return; } if (id.is_all_zeros()) { o->set_id(generate_random_id()); o->flags |= observer::flag_no_id; } o->flags |= flags; TORRENT_ASSERT(libtorrent::dht::is_sorted(m_results.begin(), m_results.end() , [this](observer_ptr const& lhs, observer_ptr const& rhs) { return compare_ref(lhs->id(), rhs->id(), m_target); })); auto iter = std::lower_bound(m_results.begin(), m_results.end(), o , [this](observer_ptr const& lhs, observer_ptr const& rhs) { return compare_ref(lhs->id(), rhs->id(), m_target); }); if (iter == m_results.end() || (*iter)->id() != id) { if (m_node.settings().restrict_search_ips && !(flags & observer::flag_initial)) { #if TORRENT_USE_IPV6 if (o->target_addr().is_v6()) { address_v6::bytes_type addr_bytes = o->target_addr().to_v6().to_bytes(); address_v6::bytes_type::const_iterator prefix_it = addr_bytes.begin(); std::uint64_t const prefix6 = detail::read_uint64(prefix_it); if (m_peer6_prefixes.insert(prefix6).second) goto add_result; } else #endif { // mask the lower octet std::uint32_t const prefix4 = o->target_addr().to_v4().to_ulong() & 0xffffff00; if (m_peer4_prefixes.insert(prefix4).second) goto add_result; } // we already have a node in this search with an IP very // close to this one. We know that it's not the same, because // it claims a different node-ID. Ignore this to avoid attacks #ifndef TORRENT_DISABLE_LOGGING dht_observer* logger = get_node().observer(); if (logger != nullptr && logger->should_log(dht_logger::traversal)) { char hex_id[41]; aux::to_hex(o->id(), hex_id); logger->log(dht_logger::traversal , "[%p] traversal DUPLICATE node. id: %s addr: %s type: %s" , static_cast<void*>(this), hex_id, print_address(o->target_addr()).c_str(), name()); } #endif return; } add_result: TORRENT_ASSERT((o->flags & observer::flag_no_id) || std::none_of(m_results.begin(), m_results.end() , [&id](observer_ptr const& ob) { return ob->id() == id; })); #ifndef TORRENT_DISABLE_LOGGING dht_observer* logger = get_node().observer(); if (logger != nullptr && logger->should_log(dht_logger::traversal)) { char hex_id[41]; aux::to_hex(id, hex_id); logger->log(dht_logger::traversal , "[%p] ADD id: %s addr: %s distance: %d invoke-count: %d type: %s" , static_cast<void*>(this), hex_id, print_endpoint(addr).c_str() , distance_exp(m_target, id), m_invoke_count, name()); } #endif iter = m_results.insert(iter, o); TORRENT_ASSERT(libtorrent::dht::is_sorted(m_results.begin(), m_results.end() , [this](observer_ptr const& lhs, observer_ptr const& rhs) { return compare_ref(lhs->id(), rhs->id(), m_target); })); } if (m_results.size() > 100) { for (int i = 100; i < int(m_results.size()); ++i) { if ((m_results[i]->flags & (observer::flag_queried | observer::flag_failed | observer::flag_alive)) == observer::flag_queried) { // set the done flag on any outstanding queries to prevent them from // calling finished() or failed() m_results[i]->flags |= observer::flag_done; TORRENT_ASSERT(m_invoke_count > 0); --m_invoke_count; } #if TORRENT_USE_ASSERTS m_results[i]->m_was_abandoned = true; #endif } m_results.resize(100); } }
bool start_client(void) { clear_console(); printf("\n\033[32m[WIFSS] Starting Client...\033[0m\n\n"); init_global_variables(); char address[BUFFER]; char *args[BUFFER]; int16_t nbArgs = -1; do { printf("-> Server IP: "); prompt_keyboard(address); free_args(args, &nbArgs); parse_command(address, args, &nbArgs); } while(nbArgs != 1); int32_t port; char portBuffer[BUFFER]; do { printf("-> Server Port: "); prompt_keyboard(portBuffer); free_args(args, &nbArgs); parse_command(portBuffer, args, &nbArgs); if(nbArgs == 1) { port = strtoul(args[0], NULL, 10); } else { port = -1; } } while(port < 0 || port > 65535); struct addrinfo *servinfo; struct addrinfo hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; int16_t status = getaddrinfo(address, args[0], &hints, &servinfo); if(status != 0) { fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while trying to get some information about your host: %s.\033[0m\n\n", gai_strerror(status)); exit(EXIT_FAILURE); } char buffer[BUFFER]; // Some stuff to set a timeout on `connect` int16_t sock = -1; int8_t error = 0; socklen_t lenght = sizeof(error); int16_t nbFds = -1; fd_set readfds; do { for(struct addrinfo *tmp = servinfo; tmp != NULL; tmp = tmp->ai_next) { /* Only for previous iterations */ if(sock != -1 && close(sock) == -1) { fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while closing a socket: %s.\033[0m\n\n", strerror(errno)); exit(EXIT_FAILURE); } /* ____________________________ */ sock = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol); if(sock == -1) { printf("\n\033[31m[WIFSS] Error while creating an endpoint for communication with server: %s.\033[0m\n\n", strerror(errno)); return false; } // Before the connection procedure, we'll set the socket as NON-BLOCKING fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, false) | O_NONBLOCK); // Let's launch the connection procedure connect(sock, tmp->ai_addr, tmp->ai_addrlen); if(errno != EINPROGRESS) { fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while running the connection procedure to: "); print_endpoint(tmp); printf(" (%s).\033[0m\n\n", strerror(errno)); continue; } // Let's now set a watch dog of 3 seconds on it FD_ZERO(&readfds); FD_SET(sock, &readfds); nbFds = select(sock + 1, &readfds, NULL, NULL, &(struct timeval){3, 0}); if(nbFds == 0) { // The timeout has been elapsed... printf("\n\033[31m[WIFSS] Error while connecting to "); print_endpoint(tmp); printf(": timeout reached.\033[0m\n"); continue; } else if(nbFds == -1) { // Again ? An error occurred... fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while waiting for the connection procedure ending: %s.\033[0m\n\n", strerror(errno)); exit(EXIT_FAILURE); } else { // Fetch the buffered SYNC data [see @server/commands.c] recv(sock, buffer, BUFFER, false); if(strcmp(buffer, CLIENT_SERVER_SYNC)) { printf("%s\n", buffer); exit(EXIT_FAILURE); } } // Two cases: The connection has been established OR a f*cking new error occurred (before the timeout !)... if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &lenght) != 0) { fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while retrieving some information about the socket: %s.\033[0m\n\n", gai_strerror(status)); exit(EXIT_FAILURE); } if(error == 0) { // For the future, let's set again the socket as BLOCKING fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, false) ^ O_NONBLOCK); // SSL stuffs SSL *ssl = SSL_new(core_variables.ctx); if(ssl == NULL) { fprintf(stderr, "\n\n\033[31mSSL Error: Couldn\'t enable the SSL layer on the socket.\n\n"); exit(EXIT_FAILURE); } if(SSL_set_cipher_list(ssl, (const char *const)"HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4") != 1) { fprintf(stderr, "\n\n\033[31mSSL Error: Couldn\'t set the ciphers list.\n\n"); exit(EXIT_FAILURE); } SSL_set_fd(ssl, sock); if(SSL_connect(ssl) <= 0) { printf("\n\n\033[31m[WIFSS] Couldn\'t create a TLS tunnel with the host...\033[0m\n\n"); ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } // SSL Verification + Certificate information if(SSL_get_verify_result(ssl) != X509_V_OK) { fprintf(stderr, "\n\n\033[31mSSL Error: The result got from SSL is not valid (is your certificate correct ?).\n\n"); exit(EXIT_FAILURE); } X509 *cert = SSL_get_peer_certificate(ssl); if(cert == NULL) { fprintf(stderr, "\n\n\033[31mSSL Error: No certificate was sent by server.\n\n"); exit(EXIT_FAILURE); } printf("\n\033[34m\tTLS cipher used for this connection: %s\n", SSL_get_cipher(ssl)); char *str = NULL; printf("\tServer certificate:\n"); str = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); printf("\t\tSubject: %s\n", (str != NULL ? str : "None")); OPENSSL_free(str); str = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); printf("\t\tIssuer : %s\033[0m\n", (str != NULL ? str : "None")); OPENSSL_free(str); X509_free(cert); // __________________________________________ core_variables.ssl = ssl; printf("\n\033[32m[WIFSS] Connected to "); print_endpoint(tmp); printf(".\033[0m\n"); strncpy(buffer, "", BUFFER); if(SSL_read(ssl, buffer, BUFFER) <= 0) { printf("\n\033[31m[WIFSS] Couldn\'t get your ID from server, exiting now.\033[0m\n\n"); exit(EXIT_FAILURE); } uint16_t idTemp = get_second_args_group_as_integer(buffer); printf("\n\033[32m[WIFSS] Your ID on the server is %d.\033[0m\n\n", idTemp); /* We save the ID of the client for the future */ core_variables.client_id = idTemp; break; } else { printf("\n\033[31m[WIFSS] Error while connecting to "); print_endpoint(tmp); printf(": %s.\033[0m\n", strerror(errno)); } } if(core_variables.client_id != -1) { // Yeah... We've to `break` the loop a second time break; } else { printf("\nWould you like to retry now ? (YES / no)\n\n"); if(!prompt_yes_no(buffer, args, &nbArgs)) { printf("\n"); return false; } } } while(true);
void traversal_observer::reply(msg const& m) { bdecode_node r = m.message.dict_find_dict("r"); if (!r) { #ifndef TORRENT_DISABLE_LOGGING if (get_observer() != nullptr) { get_observer()->log(dht_logger::traversal , "[%p] missing response dict" , static_cast<void*>(algorithm())); } #endif return; } #ifndef TORRENT_DISABLE_LOGGING dht_observer* logger = get_observer(); if (logger != nullptr && logger->should_log(dht_logger::traversal)) { bdecode_node nid = r.dict_find_string("id"); char hex_id[41]; aux::to_hex({nid.string_ptr(), 20}, hex_id); logger->log(dht_logger::traversal , "[%p] RESPONSE id: %s invoke-count: %d addr: %s type: %s" , static_cast<void*>(algorithm()), hex_id, algorithm()->invoke_count() , print_endpoint(target_ep()).c_str(), algorithm()->name()); } #endif // look for nodes #if TORRENT_USE_IPV6 udp protocol = algorithm()->get_node().protocol(); #endif char const* nodes_key = algorithm()->get_node().protocol_nodes_key(); bdecode_node n = r.dict_find_string(nodes_key); if (n) { char const* nodes = n.string_ptr(); char const* end = nodes + n.string_length(); while (end - nodes >= 20 + detail::address_size(protocol) + 2) { node_id id; std::copy(nodes, nodes + 20, id.begin()); nodes += 20; udp::endpoint ep; #if TORRENT_USE_IPV6 if (protocol == udp::v6()) ep = detail::read_v6_endpoint<udp::endpoint>(nodes); else #endif ep = detail::read_v4_endpoint<udp::endpoint>(nodes); algorithm()->traverse(id, ep); } } bdecode_node id = r.dict_find_string("id"); if (!id || id.string_length() != 20) { #ifndef TORRENT_DISABLE_LOGGING if (get_observer() != nullptr) { get_observer()->log(dht_logger::traversal, "[%p] invalid id in response" , static_cast<void*>(algorithm())); } #endif return; } // in case we didn't know the id of this peer when we sent the message to // it. For instance if it's a bootstrap node. set_id(node_id(id.string_ptr())); }