void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec) { CHECK_MAGIC; using namespace libtorrent::detail; char header[20]; char* h = header; write_uint16(0, h); // reserved write_uint8(0, h); // fragment write_uint8(ep.address().is_v4()?1:4, h); // atyp write_address(ep.address(), h); write_uint16(ep.port(), h); boost::array<asio::const_buffer, 2> iovec; iovec[0] = asio::const_buffer(header, h - header); iovec[1] = asio::const_buffer(p, len); #if TORRENT_USE_IPV6 if (m_proxy_addr.address().is_v4() && m_ipv4_sock.is_open()) #endif m_ipv4_sock.send_to(iovec, m_proxy_addr, 0, ec); #if TORRENT_USE_IPV6 else m_ipv6_sock.send_to(iovec, m_proxy_addr, 0, ec); #endif }
void rpc_manager::invoke(int message_id, udp::endpoint target_addr , observer_ptr o) { INVARIANT_CHECK; if (m_destructing) { o->abort(); return; } msg m; m.message_id = message_id; m.reply = false; m.id = m_our_id; m.addr = target_addr; TORRENT_ASSERT(!m_transactions[m_next_transaction_id]); #ifdef TORRENT_DEBUG int potential_new_id = m_next_transaction_id; #endif #ifndef BOOST_NO_EXCEPTIONS try { #endif m.transaction_id.clear(); std::back_insert_iterator<std::string> out(m.transaction_id); io::write_uint16(m_next_transaction_id, out); o->send(m); o->sent = time_now(); #if TORRENT_USE_IPV6 o->target_addr = target_addr.address(); #else o->target_addr = target_addr.address().to_v4(); #endif o->port = target_addr.port(); #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(rpc) << "Invoking " << messages::ids[message_id] << " -> " << target_addr; #endif m_send(m); new_transaction_id(o); #ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) { // m_send may fail with "no route to host" TORRENT_ASSERT(potential_new_id == m_next_transaction_id); o->abort(); } #endif }
void udp_socket::bind(udp::endpoint const& ep, error_code& ec) { if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec); if (ep.address().is_v4()) { m_ipv4_sock.open(udp::v4(), ec); if (ec) return; m_ipv4_sock.bind(ep, ec); if (ec) return; m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) , m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2)); } else { m_ipv6_sock.set_option(v6only(true), ec); if (ec) return; m_ipv6_sock.bind(ep, ec); if (ec) return; m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) , m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2)); } m_bind_port = ep.port(); }
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec) { CHECK_MAGIC; TORRENT_ASSERT(is_open()); // if the sockets are closed, the udp_socket is closing too if (!is_open()) return; if (m_tunnel_packets) { // send udp packets through SOCKS5 server wrap(ep, p, len, ec); return; } if (m_queue_packets) { m_queue.push_back(queued_packet()); queued_packet& qp = m_queue.back(); qp.ep = ep; qp.buf.insert(qp.buf.begin(), p, p + len); return; } #if TORRENT_USE_IPV6 if (ep.address().is_v4() && m_ipv4_sock.is_open()) #endif m_ipv4_sock.send_to(asio::buffer(p, len), ep, 0, ec); #if TORRENT_USE_IPV6 else m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec); #endif }
string EndpointToString(const udp::endpoint &endpoint) { string strIp = endpoint.address().to_string(); unsigned int dwPort = endpoint.port(); char szIpPort[32] = {0}; sprintf(szIpPort, "%s:%d", strIp.c_str(), dwPort); return szIpPort; }
void observer::set_target(udp::endpoint const& ep) { m_sent = clock_type::now(); m_port = ep.port(); #if TORRENT_USE_IPV6 if (ep.address().is_v6()) { flags |= flag_ipv6_address; m_addr.v6 = ep.address().to_v6().to_bytes(); } else #endif { flags &= ~flag_ipv6_address; m_addr.v4 = ep.address().to_v4().to_bytes(); } }
broadcast_socket::broadcast_socket(io_service& ios , udp::endpoint const& multicast_endpoint , receive_handler_t const& handler , bool loopback) : m_multicast_endpoint(multicast_endpoint) , m_on_receive(handler) , m_ip_broadcast(false) { TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address())); using namespace asio::ip::multicast; error_code ec; std::vector<ip_interface> interfaces = enum_net_interfaces(ios, ec); #if TORRENT_USE_IPV6 if (multicast_endpoint.address().is_v6()) open_multicast_socket(ios, address_v6::any(), loopback, ec); else #endif open_multicast_socket(ios, address_v4::any(), loopback, ec); for (std::vector<ip_interface>::const_iterator i = interfaces.begin() , end(interfaces.end()); i != end; ++i) { // only multicast on compatible networks if (i->interface_address.is_v4() != multicast_endpoint.address().is_v4()) continue; // ignore any loopback interface if (!loopback && is_loopback(i->interface_address)) continue; ec = error_code(); open_multicast_socket(ios, i->interface_address, loopback, ec); #ifndef NDEBUG // fprintf(stderr, "broadcast socket [ if: %s group: %s ] %s\n" // , i->interface_address.to_string().c_str() // , print_address(multicast_endpoint.address()).c_str() // , ec.message().c_str()); #endif open_unicast_socket(ios, i->interface_address , i->netmask.is_v4() ? i->netmask.to_v4() : address_v4()); } }
node_entry(node_id const& id_, udp::endpoint ep, int roundtriptime = 0xffff, bool pinged = false) : addr(ep.address()) , port(ep.port()) , timeout_count(pinged ? 0 : 0xffff) , rtt(roundtriptime) , id(id_) { #ifdef TORRENT_DHT_VERBOSE_LOGGING first_seen = time_now(); #endif }
node_entry(udp::endpoint ep) : addr(ep.address()) , port(ep.port()) , timeout_count(0xffff) , rtt(0xffff) , id(0) { #ifdef TORRENT_DHT_VERBOSE_LOGGING first_seen = time_now(); #endif }
bool CUDPSocket::SendData(udp::endpoint& ep, char* msg, int size, string& errInfo, unsigned long iProxyIp /*= 0*/, unsigned short iProxyPort /*= 0*/) { if(ep.address().to_v4().to_string().empty()) return false; if(ep.address().to_v4().to_string()=="255.255.255.255") return false; if(ep.port() <=0 || ep.port() >65535) return false; if(msg == NULL) return true; try { int ret = this->m_mySocket.send_to(boost::asio::buffer((const void*)msg, size), ep); if (ret < size) { return false; } } catch (const boost::system::error_code& err) { ostringstream oss; oss << "严重错误 CUDPSocket error_code2 " << err.value(); make_log_func_(oss.str()); return false; } catch (...) { ostringstream oss; oss << "严重错误..."; make_log_func_(oss.str()); return false; } return true; }
node_entry::node_entry(udp::endpoint ep) : last_queried(min_time()) , id(0) , a(ep.address().to_v4().to_bytes()) , p(ep.port()) , rtt(0xffff) , timeout_count(0xff) { #ifdef TORRENT_DHT_VERBOSE_LOGGING first_seen = aux::time_now(); #endif }
void DatagramTransceiver::sendMessage(const QString &msg, const udp::endpoint& remote_endpoint) { bool write_in_progress = m_write_msgs.empty() == false; MessageToSend* struct_msg = new MessageToSend; struct_msg->destination_endpoint.address(remote_endpoint.address()); struct_msg->destination_endpoint.port(remote_endpoint.port()); struct_msg->msg = msg; m_write_msgs.push_back(struct_msg); if (write_in_progress == false) doSend(); }
node_entry::node_entry(node_id const& id_, udp::endpoint ep , int roundtriptime , bool pinged) : last_queried(pinged ? aux::time_now() : min_time()) , id(id_) , a(ep.address().to_v4().to_bytes()) , p(ep.port()) , rtt(roundtriptime & 0xffff) , timeout_count(pinged ? 0 : 0xff) { #ifdef TORRENT_DHT_VERBOSE_LOGGING first_seen = aux::time_now(); #endif }
void observer::set_target(udp::endpoint const& ep) { #ifdef TORRENT_DHT_VERBOSE_LOGGING // use high resolution timers for logging m_sent = time_now_hires(); #else m_sent = time_now(); #endif m_port = ep.port(); #if TORRENT_USE_IPV6 if (ep.address().is_v6()) { flags |= flag_ipv6_address; m_addr.v6 = ep.address().to_v6().to_bytes(); } else #endif { flags &= ~flag_ipv6_address; m_addr.v4 = ep.address().to_v4().to_bytes(); } }
void udp_socket::bind(udp::endpoint const& ep, error_code& ec) { CHECK_MAGIC; TORRENT_ASSERT(is_single_thread()); TORRENT_ASSERT(m_abort == false); if (m_abort) { ec = boost::asio::error::operation_aborted; return; } if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); #if TORRENT_USE_IPV6 if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec); #endif if (ep.address().is_v4()) { m_ipv4_sock.open(udp::v4(), ec); if (ec) return; m_ipv4_sock.bind(ep, ec); if (ec) return; udp::socket::non_blocking_io ioc(true); m_ipv4_sock.io_control(ioc, ec); if (ec) return; setup_read(&m_ipv4_sock); } #if TORRENT_USE_IPV6 else { #ifdef IPV6_V6ONLY m_ipv6_sock.set_option(v6only(true), ec); if (ec) return; #endif m_ipv6_sock.bind(ep, ec); if (ec) return; udp::socket::non_blocking_io ioc(true); m_ipv6_sock.io_control(ioc, ec); if (ec) return; setup_read(&m_ipv6_sock); } #endif #ifdef TORRENT_DEBUG m_started = true; #endif m_bind_port = ep.port(); }
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec) { if (ec == asio::error::operation_aborted) return; if (m_tunnel_packets) { // send udp packets through SOCKS5 server wrap(ep, p, len, ec); return; } if (ep.address().is_v4() && m_ipv4_sock.is_open()) m_ipv4_sock.send_to(asio::buffer(p, len), ep, 0, ec); else m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec); }
void udp_socket::bind(udp::endpoint const& ep, error_code& ec) { CHECK_MAGIC; mutex_t::scoped_lock l(m_mutex); TORRENT_ASSERT(m_abort == false); if (m_abort) return; if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); #if TORRENT_USE_IPV6 if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec); #endif if (ep.address().is_v4()) { m_ipv4_sock.open(udp::v4(), ec); if (ec) return; m_ipv4_sock.bind(ep, ec); if (ec) return; if (m_v4_outstanding == 0) { ++m_v4_outstanding; m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) , m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2)); } } #if TORRENT_USE_IPV6 else { m_ipv6_sock.set_option(v6only(true), ec); if (ec) return; m_ipv6_sock.bind(ep, ec); if (ec) return; if (m_v6_outstanding == 0) { ++m_v6_outstanding; m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) , m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2)); } } #endif #ifdef TORRENT_DEBUG m_started = true; #endif m_bind_port = ep.port(); }
//============================================================================== // Handle Connection (uglysolution.com) // - Checks if the connection already exists. If it exists, restart timeout timer. // Else, add new connection. //============================================================================== boost::shared_ptr<Connection> ConnectionHandler::handleConnection( udp::endpoint& _endpoint ) { unsigned int connection_size = m_connections.size(); // Check if the connection already exists for( unsigned int i = 0; i < connection_size; i++ ) { if( m_connections[i]->endpoint.address().to_string().compare(_endpoint.address().to_string()) == 0 && m_connections[i]->endpoint.port() == _endpoint.port() ) { boost::shared_ptr<Connection> connection = m_connections[i]; connection->timout_timer.expires_from_now( boost::posix_time::seconds(TIMEOUT) ); connection->timout_timer.async_wait( boost::bind(&ConnectionHandler::timeout, this, connection, boost::asio::placeholders::error) ); return m_connections[i]; } } // Check if connection size is greater than the allowed amount of connections if( connection_size >= MAX_CONNECTIONS ) return boost::shared_ptr<Connection>(); // Find an connection ID m_id_counter++; for( unsigned int i = 0; i < m_connections.size(); i++ ) { if( m_connections[i]->connection_id == m_id_counter ) { m_id_counter++; i = 0; } } // Add the connection and start the timers boost::shared_ptr<Connection> new_connection( new Connection(m_id_counter, _endpoint, (*m_io_service)) ); new_connection->ack_timer.async_wait( boost::bind(&ConnectionHandler::requestAck, this, new_connection, boost::asio::placeholders::error) ); new_connection->timout_timer.async_wait( boost::bind(&ConnectionHandler::timeout, this, new_connection, boost::asio::placeholders::error) ); m_connections.push_back( new_connection ); // temp solution if( m_network_handler->isServer() ) new_connection->sync_timer.async_wait( boost::bind(&ConnectionHandler::syncClock, this, new_connection, boost::asio::placeholders::error) ); return m_connections.back(); }
bool dht_tracker::send_packet(entry& e, udp::endpoint const& addr) { static char const version_str[] = {'L', 'T' , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR }; e["v"] = std::string(version_str, version_str + 4); m_send_buf.clear(); bencode(std::back_inserter(m_send_buf), e); // update the quota. We won't prevent the packet to be sent if we exceed // the quota, we'll just (potentially) block the next incoming request. m_send_quota -= int(m_send_buf.size()); error_code ec; m_send_fun(addr, m_send_buf, ec, 0); if (ec) { m_counters.inc_stats_counter(counters::dht_messages_out_dropped); #ifndef TORRENT_DISABLE_LOGGING m_log->log_packet(dht_logger::outgoing_message, m_send_buf, addr); #endif return false; } m_counters.inc_stats_counter(counters::dht_bytes_out, m_send_buf.size()); // account for IP and UDP overhead m_counters.inc_stats_counter(counters::sent_ip_overhead_bytes , addr.address().is_v6() ? 48 : 28); m_counters.inc_stats_counter(counters::dht_messages_out); #ifndef TORRENT_DISABLE_LOGGING m_log->log_packet(dht_logger::outgoing_message, m_send_buf, addr); #endif return true; }
tuple endpoint_to_tuple(udp::endpoint const& ep) { return boost::python::make_tuple(ep.address().to_string(), ep.port()); }
void udp_socket::send(udp::endpoint const& ep, char const* p, int len , error_code& ec, int flags) { CHECK_MAGIC; TORRENT_ASSERT(is_single_thread()); // if the sockets are closed, the udp_socket is closing too if (!is_open()) { ec = error_code(boost::system::errc::bad_file_descriptor, boost::system::generic_category()); return; } if (!(flags & peer_connection) || m_proxy_settings.proxy_peer_connections) { if (m_tunnel_packets) { // send udp packets through SOCKS5 server wrap(ep, p, len, ec); return; } if (m_queue_packets) { if (m_queue.size() > 1000) return; m_queue.push_back(queued_packet()); queued_packet& qp = m_queue.back(); qp.ep = ep; qp.hostname = 0; qp.flags = flags; qp.buf.insert(qp.buf.begin(), p, p + len); return; } } if (m_force_proxy) return; #if TORRENT_USE_IPV6 if (ep.address().is_v6() && m_ipv6_sock.is_open()) m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec); else #endif m_ipv4_sock.send_to(asio::buffer(p, len), ep, 0, ec); if (ec == error::would_block || ec == error::try_again) { #if TORRENT_USE_IPV6 if (ep.address().is_v6() && m_ipv6_sock.is_open()) { if (!m_v6_write_subscribed) { m_ipv6_sock.async_send(asio::null_buffers() , boost::bind(&udp_socket::on_writable, this, _1, &m_ipv6_sock)); m_v6_write_subscribed = true; } } else #endif { if (!m_v4_write_subscribed) { m_ipv4_sock.async_send(asio::null_buffers() , boost::bind(&udp_socket::on_writable, this, _1, &m_ipv4_sock)); m_v4_write_subscribed = true; } } } }
uint64_t endpoint_to_i(const udp::endpoint& ep) { uint64_t addr_i = ep.address().to_v4().to_ulong(); uint32_t port = ep.port(); return (addr_i << 32) + port; }
void upnp::on_reply(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred) { mutex_t::scoped_lock l(m_mutex); using namespace libtorrent::detail; // parse out the url for the device /* the response looks like this: HTTP/1.1 200 OK ST:upnp:rootdevice USN:uuid:000f-66d6-7296000099dc::upnp:rootdevice Location: http://192.168.1.1:5431/dyndev/uuid:000f-66d6-7296000099dc Server: Custom/1.0 UPnP/1.0 Proc/Ver EXT: Cache-Control:max-age=180 DATE: Fri, 02 Jan 1970 08:10:38 GMT a notification looks like this: NOTIFY * HTTP/1.1 Host:239.255.255.250:1900 NT:urn:schemas-upnp-org:device:MediaServer:1 NTS:ssdp:alive Location:http://10.0.3.169:2869/upnphost/udhisapi.dll?content=uuid:c17f0c32-d19b-4938-ae94-65f945c3a26e USN:uuid:c17f0c32-d19b-4938-ae94-65f945c3a26e::urn:schemas-upnp-org:device:MediaServer:1 Cache-Control:max-age=900 Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0 */ error_code ec; if (!in_local_network(m_io_service, from.address(), ec)) { if (ec) { char msg[200]; snprintf(msg, sizeof(msg), "when receiving response from: %s: %s" , print_endpoint(from).c_str(), ec.message().c_str()); log(msg); } else { char msg[200]; int num_chars = snprintf(msg, sizeof(msg) , "ignoring response from: %s. IP is not on local network. " , print_endpoint(from).c_str()); log(msg); std::vector<ip_interface> net = enum_net_interfaces(m_io_service, ec); for (std::vector<ip_interface>::const_iterator i = net.begin() , end(net.end()); i != end; ++i) { num_chars += snprintf(msg + num_chars, sizeof(msg) - num_chars, "(%s,%s) " , print_address(i->interface_address).c_str(), print_address(i->netmask).c_str()); } log(msg); } return; } if (m_ignore_non_routers) { std::vector<ip_route> routes = enum_routes(m_io_service, ec); if (std::find_if(routes.begin(), routes.end() , bind(&ip_route::gateway, _1) == from.address()) == routes.end()) { // this upnp device is filtered because it's not in the // list of configured routers if (ec) { char msg[200]; snprintf(msg, sizeof(msg), "when receiving response from: %s: %s" , print_endpoint(from).c_str(), ec.message().c_str()); log(msg); } else { char msg[200]; int num_chars = snprintf(msg, sizeof(msg), "ignoring response from: %s: IP is not a router. " , print_endpoint(from).c_str()); for (std::vector<ip_route>::const_iterator i = routes.begin() , end(routes.end()); i != end; ++i) { num_chars += snprintf(msg + num_chars, sizeof(msg) - num_chars, "(%s,%s) " , print_address(i->gateway).c_str(), print_address(i->netmask).c_str()); } log(msg); } return; } } http_parser p; bool error = false; p.incoming(buffer::const_interval(buffer , buffer + bytes_transferred), error); if (error) { char msg[200]; snprintf(msg, sizeof(msg), "received malformed HTTP from: %s" , print_endpoint(from).c_str()); log(msg); return; } if (p.status_code() != 200 && p.method() != "notify") { if (p.method().empty()) { char msg[200]; snprintf(msg, sizeof(msg), "HTTP status %u from %s" , p.status_code(), print_endpoint(from).c_str()); log(msg); } else { char msg[200]; snprintf(msg, sizeof(msg), "HTTP method %s from %s" , p.method().c_str(), print_endpoint(from).c_str()); log(msg); } return; } if (!p.header_finished()) { char msg[200]; snprintf(msg, sizeof(msg), "incomplete HTTP packet from %s" , print_endpoint(from).c_str()); log(msg); return; } std::string url = p.header("location"); if (url.empty()) { char msg[200]; snprintf(msg, sizeof(msg), "missing location header from %s" , print_endpoint(from).c_str()); log(msg); return; } rootdevice d; d.url = url; std::set<rootdevice>::iterator i = m_devices.find(d); if (i == m_devices.end()) { std::string protocol; std::string auth; char const* error; // we don't have this device in our list. Add it boost::tie(protocol, auth, d.hostname, d.port, d.path, error) = parse_url_components(d.url); if (error) { char msg[200]; snprintf(msg, sizeof(msg), "invalid URL %s from %s: %s" , d.url.c_str(), print_endpoint(from).c_str(), error); log(msg); return; } // ignore the auth here. It will be re-parsed // by the http connection later if (protocol != "http") { char msg[200]; snprintf(msg, sizeof(msg), "unsupported protocol %s from %s" , protocol.c_str(), print_endpoint(from).c_str()); log(msg); return; } if (d.port == 0) { char msg[200]; snprintf(msg, sizeof(msg), "URL with port 0 from %s" , print_endpoint(from).c_str()); log(msg); return; } char msg[200]; snprintf(msg, sizeof(msg), "found rootdevice: %s (%d)" , d.url.c_str(), int(m_devices.size())); log(msg); if (m_devices.size() >= 50) { char msg[200]; snprintf(msg, sizeof(msg), "too many rootdevices: (%d). Ignoring %s" , int(m_devices.size()), d.url.c_str()); log(msg); return; } TORRENT_ASSERT(d.mapping.empty()); for (std::vector<global_mapping_t>::iterator j = m_mappings.begin() , end(m_mappings.end()); j != end; ++j) { mapping_t m; m.action = mapping_t::action_add; m.local_port = j->local_port; m.external_port = j->external_port; m.protocol = j->protocol; d.mapping.push_back(m); } boost::tie(i, boost::tuples::ignore) = m_devices.insert(d); } if (!m_devices.empty()) { for (std::set<rootdevice>::iterator i = m_devices.begin() , end(m_devices.end()); i != end; ++i) { if (i->control_url.empty() && !i->upnp_connection && !i->disabled) { // we don't have a WANIP or WANPPP url for this device, // ask for it rootdevice& d = const_cast<rootdevice&>(*i); TORRENT_ASSERT(d.magic == 1337); #ifndef BOOST_NO_EXCEPTIONS try { #endif char msg[200]; snprintf(msg, sizeof(msg), "connecting to: %s" , d.url.c_str()); log(msg); if (d.upnp_connection) d.upnp_connection->close(); d.upnp_connection.reset(new http_connection(m_io_service , m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2 , boost::ref(d), _5))); d.upnp_connection->get(d.url, seconds(30), 1); #ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) { (void)e; char msg[200]; snprintf(msg, sizeof(msg), "connection failed to: %s %s" , d.url.c_str(), e.what()); log(msg); d.disabled = true; } #endif } } } }
bool utp_socket_manager::incoming_packet(std::weak_ptr<utp_socket_interface> socket , udp::endpoint const& ep, span<char const> p) { // UTP_LOGV("incoming packet size:%d\n", size); if (p.size() < sizeof(utp_header)) return false; utp_header const* ph = reinterpret_cast<utp_header const*>(p.data()); // UTP_LOGV("incoming packet version:%d\n", int(ph->get_version())); if (ph->get_version() != 1) return false; const time_point receive_time = clock_type::now(); // parse out connection ID and look for existing // connections. If found, forward to the utp_stream. std::uint16_t id = ph->connection_id; // first test to see if it's the same socket as last time // in most cases it is if (m_last_socket && utp_match(m_last_socket, ep, id)) { return utp_incoming_packet(m_last_socket, p, ep, receive_time); } std::pair<socket_map_t::iterator, socket_map_t::iterator> r = m_utp_sockets.equal_range(id); for (; r.first != r.second; ++r.first) { if (!utp_match(r.first->second, ep, id)) continue; bool ret = utp_incoming_packet(r.first->second, p, ep, receive_time); if (ret) m_last_socket = r.first->second; return ret; } // UTP_LOGV("incoming packet id:%d source:%s\n", id, print_endpoint(ep).c_str()); if (!m_sett.get_bool(settings_pack::enable_incoming_utp)) return false; // if not found, see if it's a SYN packet, if it is, // create a new utp_stream if (ph->get_type() == ST_SYN) { // possible SYN flood. Just ignore if (int(m_utp_sockets.size()) > m_sett.get_int(settings_pack::connections_limit) * 2) return false; // UTP_LOGV("not found, new connection id:%d\n", m_new_connection); std::shared_ptr<socket_type> c(new (std::nothrow) socket_type(m_ios)); if (!c) return false; TORRENT_ASSERT(m_new_connection == -1); // create the new socket with this ID m_new_connection = id; instantiate_connection(m_ios, aux::proxy_settings(), *c , m_ssl_context, this, true, false); utp_stream* str = nullptr; #ifdef TORRENT_USE_OPENSSL if (is_ssl(*c)) str = &c->get<ssl_stream<utp_stream>>()->next_layer(); else #endif str = c->get<utp_stream>(); TORRENT_ASSERT(str); int link_mtu, utp_mtu; mtu_for_dest(ep.address(), link_mtu, utp_mtu); utp_init_mtu(str->get_impl(), link_mtu, utp_mtu); utp_init_socket(str->get_impl(), socket); bool ret = utp_incoming_packet(str->get_impl(), p, ep, receive_time); if (!ret) return false; m_cb(c); // the connection most likely changed its connection ID here // we need to move it to the correct ID return true; } if (ph->get_type() == ST_RESET) return false; // #error send reset return false; }
void lsd::on_announce(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred) { using namespace libtorrent::detail; http_parser p; bool error = false; p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred) , error); if (!p.header_finished() || error) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (m_log) fprintf(m_log, "%s <== announce: incomplete HTTP message\n", time_now_string()); #endif return; } if (p.method() != "bt-search") { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (m_log) fprintf(m_log, "%s <== announce: invalid HTTP method: %s\n" , time_now_string(), p.method().c_str()); #endif return; } std::string const& port_str = p.header("port"); if (port_str.empty()) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (m_log) fprintf(m_log, "%s <== announce: invalid BT-SEARCH, missing port\n" , time_now_string()); #endif return; } int port = std::atoi(port_str.c_str()); typedef std::multimap<std::string, std::string> headers_t; headers_t const& headers = p.headers(); headers_t::const_iterator cookie_iter = headers.find("cookie"); if (cookie_iter != headers.end()) { // we expect it to be hexadecimal // if it isn't, it's not our cookie anyway boost::int32_t cookie = strtol(cookie_iter->second.c_str(), NULL, 16); if (cookie == m_cookie) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (m_log) fprintf(m_log, "%s <== announce: ignoring packet (cookie matched our own): %x == %x\n" , time_now_string(), cookie, m_cookie); #endif return; } } std::pair<headers_t::const_iterator, headers_t::const_iterator> ihs = headers.equal_range("infohash"); for (headers_t::const_iterator i = ihs.first; i != ihs.second; ++i) { std::string const& ih_str = i->second; if (ih_str.size() != 40) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (m_log) fprintf(m_log, "%s <== announce: invalid BT-SEARCH, invalid infohash: %s\n" , time_now_string(), ih_str.c_str()); #endif continue; } sha1_hash ih(0); from_hex(ih_str.c_str(), 40, (char*)&ih[0]); if (!ih.is_all_zeros() && port != 0) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (m_log) fprintf(m_log, "%s *** incoming local announce %s:%d ih: %s\n" , time_now_string(), print_address(from.address()).c_str() , port, ih_str.c_str()); #endif // we got an announce, pass it on through the callback TORRENT_TRY { m_callback(tcp::endpoint(from.address(), port), ih); } TORRENT_CATCH(std::exception&) {} } } }
bool dht_tracker::incoming_packet(udp::endpoint const& ep , span<char const> const buf) { int const buf_size = int(buf.size()); if (buf_size <= 20 || buf.front() != 'd' || buf.back() != 'e') return false; m_counters.inc_stats_counter(counters::dht_bytes_in, buf_size); // account for IP and UDP overhead m_counters.inc_stats_counter(counters::recv_ip_overhead_bytes , ep.address().is_v6() ? 48 : 28); m_counters.inc_stats_counter(counters::dht_messages_in); if (m_settings.ignore_dark_internet && ep.address().is_v4()) { address_v4::bytes_type b = ep.address().to_v4().to_bytes(); // these are class A networks not available to the public // if we receive messages from here, that seems suspicious static std::uint8_t const class_a[] = { 3, 6, 7, 9, 11, 19, 21, 22, 25 , 26, 28, 29, 30, 33, 34, 48, 51, 56 }; if (std::find(std::begin(class_a), std::end(class_a), b[0]) != std::end(class_a)) { m_counters.inc_stats_counter(counters::dht_messages_in_dropped); return true; } } if (!m_blocker.incoming(ep.address(), clock_type::now(), m_log)) { m_counters.inc_stats_counter(counters::dht_messages_in_dropped); return true; } TORRENT_ASSERT(buf_size > 0); int pos; error_code err; int ret = bdecode(buf.data(), buf.data() + buf_size, m_msg, err, &pos, 10, 500); if (ret != 0) { m_counters.inc_stats_counter(counters::dht_messages_in_dropped); #ifndef TORRENT_DISABLE_LOGGING m_log->log_packet(dht_logger::incoming_message, buf, ep); #endif return false; } if (m_msg.type() != bdecode_node::dict_t) { m_counters.inc_stats_counter(counters::dht_messages_in_dropped); #ifndef TORRENT_DISABLE_LOGGING m_log->log_packet(dht_logger::incoming_message, buf, ep); #endif // it's not a good idea to send a response to an invalid messages return false; } #ifndef TORRENT_DISABLE_LOGGING m_log->log_packet(dht_logger::incoming_message, buf, ep); #endif libtorrent::dht::msg m(m_msg, ep); m_dht.incoming(m); #if TORRENT_USE_IPV6 m_dht6.incoming(m); #endif return true; }
inline std::string print_endpoint(udp::endpoint const& ep) { return print_endpoint(tcp::endpoint(ep.address(), ep.port())); }
bool utp_socket_manager::incoming_packet(error_code const& ec, udp::endpoint const& ep , char const* p, int size) { // UTP_LOGV("incoming packet size:%d\n", size); if (size < int(sizeof(utp_header))) return false; utp_header const* ph = (utp_header*)p; // UTP_LOGV("incoming packet version:%d\n", int(ph->get_version())); if (ph->get_version() != 1) return false; const ptime receive_time = time_now_hires(); // parse out connection ID and look for existing // connections. If found, forward to the utp_stream. boost::uint16_t id = ph->connection_id; // first test to see if it's the same socket as last time // in most cases it is if (m_last_socket && utp_match(m_last_socket, ep, id)) { return utp_incoming_packet(m_last_socket, p, size, ep, receive_time); } std::pair<socket_map_t::iterator, socket_map_t::iterator> r = m_utp_sockets.equal_range(id); for (; r.first != r.second; ++r.first) { if (!utp_match(r.first->second, ep, id)) continue; bool ret = utp_incoming_packet(r.first->second, p, size, ep, receive_time); if (ret) m_last_socket = r.first->second; return ret; } // UTP_LOGV("incoming packet id:%d source:%s\n", id, print_endpoint(ep).c_str()); if (!m_sett.enable_incoming_utp) return false; // if not found, see if it's a SYN packet, if it is, // create a new utp_stream if (ph->get_type() == ST_SYN) { // possible SYN flood. Just ignore if (m_utp_sockets.size() > m_sett.connections_limit * 2) return false; // UTP_LOGV("not found, new connection id:%d\n", m_new_connection); boost::shared_ptr<socket_type> c(new (std::nothrow) socket_type(m_sock.get_io_service())); if (!c) return false; TORRENT_ASSERT(m_new_connection == -1); // create the new socket with this ID m_new_connection = id; instantiate_connection(m_sock.get_io_service(), proxy_settings(), *c, 0, this); utp_stream* str = c->get<utp_stream>(); TORRENT_ASSERT(str); int link_mtu, utp_mtu; mtu_for_dest(ep.address(), link_mtu, utp_mtu); utp_init_mtu(str->get_impl(), link_mtu, utp_mtu); bool ret = utp_incoming_packet(str->get_impl(), p, size, ep, receive_time); if (!ret) return false; m_cb(c); // the connection most likely changed its connection ID here // we need to move it to the correct ID return true; } // #error send reset return false; }
void lsd::on_announce(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred) { using namespace libtorrent::detail; http_parser p; bool error = false; p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred) , error); if (!p.header_finished() || error) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << time_now_string() << " <== announce: incomplete HTTP message\n"; #endif return; } if (p.method() != "bt-search") { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << time_now_string() << " <== announce: invalid HTTP method: " << p.method() << std::endl; #endif return; } std::string const& port_str = p.header("port"); if (port_str.empty()) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << time_now_string() << " <== announce: invalid BT-SEARCH, missing port" << std::endl; #endif return; } std::string const& ih_str = p.header("infohash"); if (ih_str.empty()) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << time_now_string() << " <== announce: invalid BT-SEARCH, missing infohash" << std::endl; #endif return; } sha1_hash ih(0); std::istringstream ih_sstr(ih_str); ih_sstr >> ih; int port = std::atoi(port_str.c_str()); if (!ih.is_all_zeros() && port != 0) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << time_now_string() << " *** incoming local announce " << from.address() << ":" << to_string(port).elems << " ih: " << ih << std::endl; #endif // we got an announce, pass it on through the callback #ifndef BOOST_NO_EXCEPTIONS try { #endif m_callback(tcp::endpoint(from.address(), port), ih); #ifndef BOOST_NO_EXCEPTIONS } catch (std::exception&) {} #endif } }
long UdpTransport::send_buffer( const udp::endpoint& target, const char* buf, size_t size) { uint64_t bytes_sent = 0; int send_attempts = -1; ssize_t actual_sent = -1; while (actual_sent < 0 && (settings_.resend_attempts < 0 || send_attempts < settings_.resend_attempts)) { if(settings_.max_send_hertz > 0) { enforcer_.sleep_until_next(); } // send the fragment try { actual_sent = socket_.send_to(asio::buffer(buf, size), target); } catch (const boost::system::system_error& e) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "UdpTransport::send_buffer:" " Error sending packet to %s:%d: %s\n", target.address().to_string().c_str(), (int)target.port(), e.what()); // ensure erroneous data is not being used actual_sent = -1; } ++send_attempts; if(settings_.debug_to_kb_prefix != "") { ++sent_packets; } if(actual_sent > 0) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "UdpTransport::send_buffer: Sent %d byte packet to %s:%d\n", (int)actual_sent, target.address().to_string().c_str(), (int)target.port()); bytes_sent += actual_sent; if(settings_.debug_to_kb_prefix != "") { sent_data += actual_sent; if(sent_data_max < actual_sent) { sent_data_max = actual_sent; } if(sent_data_min > actual_sent || sent_data_min == 0) { sent_data_min = actual_sent; } } } else { if(settings_.debug_to_kb_prefix != "") { ++failed_sends; } } } return (long)bytes_sent; }