// send an outgoing message to a remote host, if addr is given, then message is sent via UDP // return the number of bytes sent size_t net_ace:: send (id_t target, char const *msg, size_t size, const Addr *addr) { if (_active == false) return 0; // NOTE: it's possible that connection is already broken, yet still try to access connection // (remote disconnect + local send), may crash. So mutex has to be used // a TCP message if (addr == NULL) { std::map<id_t, ConnectInfo>::iterator it; timestamp_t now = this->getTimestamp (); _conn_mutex.acquire (); // need to check if stream object still exists, otherwise may crash // (remote disconnection could already remove the connection) if ((it = _id2conn.find (target)) != _id2conn.end ()) { // TODO: perhaps actual send can be done outside of mutex (avoid locking too long?) #ifdef VAST_USE_SSL if (it->second.is_secure) { ACE_SSL_SOCK_Stream &stream = ((net_ace_handler *)(it->second.stream))->getSSLStream (); size = stream.send_n (msg, size); } else { #endif ACE_SOCK_Stream &stream = *((net_ace_handler *)(it->second.stream)); size = stream.send_n (msg, size); #ifdef VAST_USE_SSL } #endif // update the last accessed time for this connection it->second.lasttime = now; } else size = 0; _conn_mutex.release (); } // a UDP message else { // TODO: check if two threads accessing same data structure can occur ACE_INET_Addr target_addr ((u_short)addr->publicIP.port, (ACE_UINT32)addr->publicIP.host); size = _udp->send (msg, size, target_addr); // NOTE: there's no time update for UDP connection, as there's no need for connection timeout } return size; }
int method_datagram_t::connect_fd() { const netaddr_t& addr = target_addr(); int fd = socket(addr.sa->sa_family, SOCK_DGRAM, 0); if(fd < 0) { throw exception_sys_t(log::error, errno, "socket: %m"); } bq_fd_setup(fd); if(bq_connect(fd, addr.sa, addr.sa_len, NULL) < 0) { throw exception_sys_t(log::error, errno, "connect: %m"); } return fd; }
ICMPv6::ICMPv6(const uint8_t *buffer, uint32_t total_sz) : _options_size(), reach_time(0), retrans_timer(0) { if(total_sz < sizeof(_header)) throw malformed_packet(); std::memcpy(&_header, buffer, sizeof(_header)); buffer += sizeof(_header); total_sz -= sizeof(_header); if(has_target_addr()) { if(total_sz < ipaddress_type::address_size) throw malformed_packet(); target_addr(buffer); buffer += ipaddress_type::address_size; total_sz -= ipaddress_type::address_size; } if(has_dest_addr()) { if(total_sz < ipaddress_type::address_size) throw malformed_packet(); dest_addr(buffer); buffer += ipaddress_type::address_size; total_sz -= ipaddress_type::address_size; } if(type() == ROUTER_ADVERT) { if(total_sz < sizeof(uint32_t) * 2) throw malformed_packet(); const uint32_t *ptr_32 = (const uint32_t*)buffer; reach_time = *ptr_32++; retrans_timer = *ptr_32++; buffer += sizeof(uint32_t) * 2; total_sz -= sizeof(uint32_t) * 2; } if(has_options()) parse_options(buffer, total_sz); if(total_sz > 0) inner_pdu(new RawPDU(buffer, total_sz)); }
udp::endpoint observer::target_ep() const { return udp::endpoint(target_addr(), m_port); }
Dot11ControlTA::Dot11ControlTA(const address_type &dst_addr, const address_type &target_address) : Dot11Control(dst_addr) { target_addr(target_address); }
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 net_ace:: connect (id_t target, unsigned int host, unsigned short port, bool is_secure) { if (_active == false) return false; // we're always connected to self if (target == _id || isConnected (target)) { printf ("net_ace::connect () connection for [%llu] already exists\n", target); return true; } // convert target address to ACE format ACE_INET_Addr target_addr (port, (ACE_UINT32)host); // create new handler net_ace_handler *handler; ACE_NEW_RETURN (handler, net_ace_handler, false); // initialize a connection, note that handler is treated as a SOCK_Stream object // NOTE 2nd parameter in ACE_Time_Value is in microsecond (not milli) int attempt_count = 0; ACE_Time_Value sleeptime (0, 100000); ACE_DEBUG ((LM_DEBUG, "connecting to %s:%u (%s)\n", target_addr.get_host_addr (), port, (is_secure ? "secure" : "non-secure"))); // three-second TCP connection timeout ACE_Time_Value timeout (3, 0); while (attempt_count <= RECONNECT_ATTEMPT) { int result; #ifdef VAST_USE_SSL if (is_secure) { result = _SSL_connector.connect (handler->getSSLStream (), target_addr, &timeout); printf ("making secure connection, result: %d\n", result); } else #endif result = _connector.connect (*handler, target_addr, &timeout); // if attempt succeed if (result == 0) break; attempt_count++; ACE_DEBUG ((LM_DEBUG, "connect %s:%d failed (try %d):\n", target_addr.get_host_addr (), target_addr.get_port_number (), attempt_count)); ACE_OS::sleep (sleeptime); } // see if we've failed if (attempt_count > RECONNECT_ATTEMPT) ACE_ERROR_RETURN ((LM_ERROR, "connect to %s:%u (%s) failed after %d re-attempts\n", target_addr.get_host_addr (), target_addr.get_port_number (), (is_secure ? "secure" : "normal"), attempt_count), false); // open the handler object, this will // 1) register handler with reactor 2) cause socket_connected () be called if (handler->open (_reactor, this, target) == -1) { handler->close(); return false; } ACE_DEBUG ((LM_DEBUG, "(%5t) connect(): connected to (%s:%d)\n", target_addr.get_host_addr (), target_addr.get_port_number ())); return true; }