tcp::endpoint utp_socket_manager::local_endpoint(address const& remote, error_code& ec) const { tcp::endpoint socket_ep = m_sock.local_endpoint(ec); // first enumerate the routes in the routing table if (time_now() - m_last_route_update > seconds(60)) { m_last_route_update = time_now(); error_code ec; m_routes = enum_routes(m_sock.get_io_service(), ec); if (ec) return socket_ep; } if (m_routes.empty()) return socket_ep; // then find the best match ip_route* best = &m_routes[0]; for (std::vector<ip_route>::iterator i = m_routes.begin() , end(m_routes.end()); i != end; ++i) { if (is_any(i->destination) && i->destination.is_v4() == remote.is_v4()) { best = &*i; continue; } if (match_addr_mask(remote, i->destination, i->netmask)) { best = &*i; continue; } } // best now tells us which interface we would send over // for this target. Now figure out what the local address // is for that interface if (time_now() - m_last_if_update > seconds(60)) { m_last_if_update = time_now(); error_code ec; m_interfaces = enum_net_interfaces(m_sock.get_io_service(), ec); if (ec) return socket_ep; } for (std::vector<ip_interface>::iterator i = m_interfaces.begin() , end(m_interfaces.end()); i != end; ++i) { if (i->interface_address.is_v4() != remote.is_v4()) continue; if (strcmp(best->name, i->name) == 0) return tcp::endpoint(i->interface_address, socket_ep.port()); } return socket_ep; }
address get_default_gateway(io_service& ios, error_code& ec) { std::vector<ip_route> ret = enum_routes(ios, ec); #if defined TORRENT_WINDOWS || defined TORRENT_MINGW std::vector<ip_route>::iterator i = std::find_if(ret.begin(), ret.end() , boost::bind(&is_loopback, boost::bind(&ip_route::destination, _1))); #else std::vector<ip_route>::iterator i = std::find_if(ret.begin(), ret.end() , boost::bind(&ip_route::destination, _1) == address()); #endif if (i == ret.end()) return address(); return i->gateway; }
void utp_socket_manager::mtu_for_dest(address const& addr, int& link_mtu, int& utp_mtu) { if (time_now() - m_last_route_update > seconds(60)) { m_last_route_update = time_now(); error_code ec; m_routes = enum_routes(m_sock.get_io_service(), ec); } int mtu = 0; if (!m_routes.empty()) { for (std::vector<ip_route>::iterator i = m_routes.begin() , end(m_routes.end()); i != end; ++i) { if (!match_addr_mask(addr, i->destination, i->netmask)) continue; // assume that we'll actually use the route with the largest // MTU (seems like a reasonable assumption). // this could however be improved by using the route metrics // and the prefix length of the netmask to order the matches if (mtu < i->mtu) mtu = i->mtu; } } if (mtu == 0) { if (is_teredo(addr)) mtu = TORRENT_TEREDO_MTU; else mtu = TORRENT_ETHERNET_MTU; } // clamp the MTU within reasonable bounds if (mtu < TORRENT_INET_MIN_MTU) mtu = TORRENT_INET_MIN_MTU; else if (mtu > TORRENT_INET_MAX_MTU) mtu = TORRENT_INET_MAX_MTU; link_mtu = mtu; mtu -= TORRENT_UDP_HEADER; if (m_sock.get_proxy_settings().type == proxy_settings::socks5 || m_sock.get_proxy_settings().type == proxy_settings::socks5_pw) { // this is for the IP layer address proxy_addr = m_sock.proxy_addr().address(); if (proxy_addr.is_v4()) mtu -= TORRENT_IPV4_HEADER; else mtu -= TORRENT_IPV6_HEADER; // this is for the SOCKS layer mtu -= TORRENT_SOCKS5_HEADER; // the address field in the SOCKS header if (addr.is_v4()) mtu -= 4; else mtu -= 16; } else { if (addr.is_v4()) mtu -= TORRENT_IPV4_HEADER; else mtu -= TORRENT_IPV6_HEADER; } utp_mtu = mtu; }