void utp_socket_manager::mtu_for_dest(address const& addr, int& link_mtu, int& utp_mtu)
	{

		int mtu = 0;
		if (is_teredo(addr)) mtu = TORRENT_TEREDO_MTU;
		else mtu = TORRENT_ETHERNET_MTU;

#if defined __APPLE__
		// apple has a very strange loopback. It appears you can't
		// send messages of the reported MTU size, and you don't get
		// EWOULDBLOCK either.
		if (is_loopback(addr))
		{
			if (is_teredo(addr)) mtu = TORRENT_TEREDO_MTU;
			else mtu = TORRENT_ETHERNET_MTU;
		}
#endif

		// 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 == settings_pack::socks5
			|| m_sock.get_proxy_settings().type == settings_pack::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 = (std::min)(mtu, restrict_mtu());
	}
Example #2
0
	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;
	}