TEST_F(TestNetworkProviderInMemory, PacketLoss50Percent)
{
    OClock testTime{Clock::now()};
    std::vector<uint8_t> payload = {1,2,3,4};

    NetworkProviderInMemory::RandomSettings settings{
                std::bind(myRandom0To1, myRandomEngine),
                {},
                Milliseconds{0},
                0.5f,
                0.75f,
                0};

    NetworkProviderInMemory buffer(settings, [&testTime] () -> OClock { return testTime; });

    auto addressServer = udp::endpoint{address_v4(1l), 13444};
    auto addressClient = udp::endpoint{address_v4(2l), 4444};
    auto packetToClient = NetworkPacket{payload, addressClient};

    buffer.RunAs(addressServer);
    buffer.Send({packetToClient, packetToClient, packetToClient, packetToClient, packetToClient, packetToClient, packetToClient, packetToClient});

    buffer.RunAs(addressClient);
    auto result = buffer.Receive();

    EXPECT_NE(result.size(), 8);
    EXPECT_NE(result.size(), 0);
}
Пример #2
0
		libtorrent::address address() const
		{
#if TORRENT_USE_IPV6
			if (v4) return address_v4(addr.v4);
			else return address_v6(addr.v6);
#else
			return address_v4(addr.v4);
#endif
		}
Пример #3
0
		operator udp::endpoint() const
		{
#if TORRENT_USE_IPV6
			if (v4) return udp::endpoint(address_v4(addr.v4), port);
			else return udp::endpoint(address_v6(addr.v6), port);
#else
			return udp::endpoint(address_v4(addr.v4), port);
#endif
		}
TEST_F(TestNetworkProviderInMemory, LatencyInOrder)
{
    OClock testTime{Clock::now()};
    std::vector<std::vector<uint8_t>> payloads = {{1,2,3,4}, {4,4}, {3,5,6,7}, {8,8,8,8,8,8,8,8}};

    NetworkProviderInMemory::RandomSettings settings{
                std::bind(myRandom0To1, myRandomEngine),
                std::bind(myLatency, myRandomEngine),
                Milliseconds{100},
                0,
                0,
                0};

    NetworkProviderInMemory buffer(settings, [&testTime] () -> OClock { return testTime; });


    auto addressServer = udp::endpoint{address_v4(1l), 13444};
    auto addressClient = udp::endpoint{address_v4(2l), 4444};
    auto packets = std::vector<NetworkPacket>{};
    for (auto payload : payloads)
    {
        packets.emplace_back(payload, addressClient);
    }

    buffer.RunAs(addressServer);
    for (int i = 0; i < 8; i++)
    {
        buffer.Send(packets);
        testTime += std::chrono::milliseconds(10);
    }

    testTime -= std::chrono::milliseconds(8 * 10);

    buffer.RunAs(addressClient);
    auto result = buffer.Receive();
    EXPECT_EQ(result.size(), 0);

    // Minimum latency is 100 ms.
    testTime -= std::chrono::milliseconds(99);
    result = buffer.Receive();
    EXPECT_EQ(result.size(), 0);

    // Should get all packets after 1 second.
    testTime += std::chrono::milliseconds(1001);
    result = buffer.Receive();
    EXPECT_EQ(result.size(), 8 * payloads.size());

    int i = 0;
    for (auto& packet : result)
    {
        EXPECT_EQ(payloads[i], packet.data);
        i = (i + 1) % payloads.size();
    }
}
Пример #5
0
			bool can_broadcast() const
			{
				error_code ec;
				return broadcast
					&& netmask != address_v4()
					&& socket->local_endpoint(ec).address().is_v4();
			}
Пример #6
0
	address external_ip::external_address(address const& ip) const
	{
		address ext = m_vote_group[ip.is_v6()].external_address();
#if TORRENT_USE_IPV6
		if (ip.is_v6() && ext == address_v4()) return address_v6();
#endif
		return ext;
	}
Пример #7
0
			address_v4 broadcast_address() const
			{
				error_code ec;
#if BOOST_VERSION < 104700
				return address_v4(socket->local_endpoint(ec).address().to_v4().to_ulong() | ((~netmask.to_ulong()) & 0xffffffff));
#else
				return address_v4::broadcast(socket->local_endpoint(ec).address().to_v4(), netmask);
#endif
			}
TEST_F(TestNetworkProviderInMemory, NoLatency)
{
    NetworkProviderInMemory buffer{};
    std::vector<uint8_t> payloads[2] = {{1,2,3,4}, {6,7,8,9,10}};

    auto addressServer = udp::endpoint{address_v4(1l), 13444};
    auto addressClient = udp::endpoint{address_v4(2l), 4444};
    auto packetToClient = NetworkPacket{payloads[1], addressClient};

    buffer.RunAs(addressServer);
    buffer.Send({packetToClient});

    buffer.RunAs(addressClient);
    auto result = buffer.Receive();

    ASSERT_EQ(1, result.size());
    EXPECT_EQ(payloads[1], result[0].data);
}
Пример #9
0
address observer::target_addr() const
{
#if TORRENT_USE_IPV6
	if (flags & flag_ipv6_address)
		return address_v6(m_addr.v6);
	else
#endif
		return address_v4(m_addr.v4);
}
Пример #10
0
		tcp::endpoint peer() const
		{
#if TORRENT_USE_IPV6
			if (is_v6_addr)
				return tcp::endpoint(address_v6(addr.v6), port);
			else
#endif
				return tcp::endpoint(address_v4(addr.v4), port);
		}
TEST_F(TestNetworkProviderInMemory, LatencyOutOfOrder)
{
    OClock testTime{Clock::now()};
    std::vector<std::vector<uint8_t>> payloads = {{1,2,3,4}, {4,4}, {3,5,6,7}, {8,8,8,8,8,8,8,8}};


    NetworkProviderInMemory::RandomSettings settings{
                std::bind(myRandom0To1, myRandomEngine),
                std::bind(myLatency, myRandomEngine),
                Milliseconds{100},
                0,
                0,
                1.0};

    NetworkProviderInMemory buffer(settings, [&testTime] () -> OClock { return testTime; });

    auto addressServer = udp::endpoint{address_v4(1l), 13444};
    auto addressClient = udp::endpoint{address_v4(2l), 4444};
    auto packets = std::vector<NetworkPacket>{};
    for (auto payload : payloads)
    {
        packets.emplace_back(payload, addressClient);
    }

    buffer.RunAs(addressServer);
    buffer.Send(packets);

    testTime += std::chrono::milliseconds(1000);

    buffer.RunAs(addressClient);
    auto result = buffer.Receive();
    EXPECT_EQ(result.size(), payloads.size());

    bool inOrder = true;
    for (std::size_t i = 0; i < result.size(); ++i)
    {
        if (result[i].data != payloads[i])
        {
            inOrder = false;
        }
    }

    EXPECT_FALSE(inOrder);
}
Пример #12
0
	address build_netmask(int bits, int family)
	{
		if (family == AF_INET)
		{
			typedef asio::ip::address_v4::bytes_type bytes_t;
			bytes_t b;
			std::memset(&b[0], 0xff, b.size());
			for (int i = sizeof(bytes_t)/8-1; i > 0; --i)
			{
				if (bits < 8)
				{
					b[i] <<= bits;
					break;
				}
				b[i] = 0;
				bits -= 8;
			}
			return address_v4(b);
		}
#if TORRENT_USE_IPV6
		else if (family == AF_INET6)
		{
			typedef asio::ip::address_v6::bytes_type bytes_t;
			bytes_t b;
			std::memset(&b[0], 0xff, b.size());
			for (int i = sizeof(bytes_t)/8-1; i > 0; --i)
			{
				if (bits < 8)
				{
					b[i] <<= bits;
					break;
				}
				b[i] = 0;
				bits -= 8;
			}
			return address_v6(b);
		}
#endif
		else
		{
			return address();
		}
	}
Пример #13
0
BOOST_FIXTURE_TEST_CASE(Tcp, ResolverFixture<tcp>)
{
  TcpResolver::asyncResolve("www.named-data.net", "6363",
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v4(), 6363), true, false),
                            bind(&ResolverFixture<tcp>::onFailure, this, false));

  TcpResolver::asyncResolve("www.named-data.net", "notport",
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v4(), 0), false, false),
                            bind(&ResolverFixture<tcp>::onFailure, this, true)); // should fail


  TcpResolver::asyncResolve("nothost.nothost.nothost.arpa", "6363",
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v4(), 6363), false, false),
                            bind(&ResolverFixture<tcp>::onFailure, this, true)); // should fail

  TcpResolver::asyncResolve("www.google.com", "80",
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v4(), 80), true, false),
                            bind(&ResolverFixture<tcp>::onFailure, this, false),
                            resolver::Ipv4Address()); // request IPv4 address

  TcpResolver::asyncResolve("www.google.com", "80",
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v6(), 80), true, false),
                            bind(&ResolverFixture<tcp>::onFailure, this, false),
                            resolver::Ipv6Address()); // request IPv6 address

  TcpResolver::asyncResolve("ipv6.google.com", "80", // only IPv6 address should be available
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v6(), 80), true, false),
                            bind(&ResolverFixture<tcp>::onFailure, this, false));

  TcpResolver::asyncResolve("ipv6.google.com", "80", // only IPv6 address should be available
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v6(), 80), true, false),
                            bind(&ResolverFixture<tcp>::onFailure, this, false),
                            resolver::Ipv6Address());

  TcpResolver::asyncResolve("ipv6.google.com", "80", // only IPv6 address should be available
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v6(), 80), false, false),
                            bind(&ResolverFixture<tcp>::onFailure, this, true), // should fail
                            resolver::Ipv4Address());

  TcpResolver::asyncResolve("192.0.2.1", "80",
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v4::from_string("192.0.2.1"), 80), true, true),
                            bind(&ResolverFixture<tcp>::onFailure, this, false));

  TcpResolver::asyncResolve("2001:db8:3f9:0:3025:ccc5:eeeb:86d3", "80",
                            bind(&ResolverFixture<tcp>::onSuccess, this, _1,
                                 tcp::endpoint(address_v6::
                                               from_string("2001:db8:3f9:0:3025:ccc5:eeeb:86d3"),
                                               80), true, true),
                            bind(&ResolverFixture<tcp>::onFailure, this, false));

  g_io.run();

  BOOST_CHECK_EQUAL(m_nFailures, 3);
  BOOST_CHECK_EQUAL(m_nSuccesses, 7);
}
Пример #14
0
	std::vector<ip_route> enum_routes(io_service& ios, error_code& ec)
	{
		std::vector<ip_route> ret;
		TORRENT_UNUSED(ios);

#ifdef TORRENT_BUILD_SIMULATOR

		TORRENT_UNUSED(ec);

		std::vector<address> ips = ios.get_ips();

		for (int i = 0; i < int(ips.size()); ++i)
		{
			ip_route r;
			if (ips[i].is_v4())
			{
				r.destination = address_v4();
				r.netmask = address_v4::from_string("255.255.255.0");
				address_v4::bytes_type b = ips[i].to_v4().to_bytes();
				b[3] = 1;
				r.gateway = address_v4(b);
			}
			else
			{
				r.destination = address_v6();
				r.netmask = address_v6::from_string("FFFF:FFFF:FFFF:FFFF::0");
				address_v6::bytes_type b = ips[i].to_v6().to_bytes();
				b[14] = 1;
				r.gateway = address_v6(b);
			}
			strcpy(r.name, "eth0");
			r.mtu = ios.sim().config().path_mtu(ips[i], ips[i]);
			ret.push_back(r);
		}

#elif TORRENT_USE_SYSCTL
/*
		struct rt_msg
		{
			rt_msghdr m_rtm;
			char buf[512];
		};

		rt_msg m;
		int len = sizeof(rt_msg);
		bzero(&m, len);
		m.m_rtm.rtm_type = RTM_GET;
		m.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
		m.m_rtm.rtm_version = RTM_VERSION;
		m.m_rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
		m.m_rtm.rtm_seq = 0;
		m.m_rtm.rtm_msglen = len;

		int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
		if (s == -1)
		{
			ec = error_code(errno, boost::asio::error::system_category);
			return std::vector<ip_route>();
		}

		int n = write(s, &m, len);
		if (n == -1)
		{
			ec = error_code(errno, boost::asio::error::system_category);
			close(s);
			return std::vector<ip_route>();
		}
		else if (n != len)
		{
			ec = boost::asio::error::operation_not_supported;
			close(s);
			return std::vector<ip_route>();
		}
		bzero(&m, len);

		n = read(s, &m, len);
		if (n == -1)
		{
			ec = error_code(errno, boost::asio::error::system_category);
			close(s);
			return std::vector<ip_route>();
		}

		for (rt_msghdr* ptr = &m.m_rtm; (char*)ptr < ((char*)&m.m_rtm) + n; ptr = (rt_msghdr*)(((char*)ptr) + ptr->rtm_msglen))
		{
			std::cout << " rtm_msglen: " << ptr->rtm_msglen << std::endl;
			std::cout << " rtm_type: " << ptr->rtm_type << std::endl;
			if (ptr->rtm_errno)
			{
				ec = error_code(ptr->rtm_errno, boost::asio::error::system_category);
				return std::vector<ip_route>();
			}
			if (m.m_rtm.rtm_flags & RTF_UP == 0
				|| m.m_rtm.rtm_flags & RTF_GATEWAY == 0)
			{
				ec = boost::asio::error::operation_not_supported;
				return address_v4::any();
			}
			if (ptr->rtm_addrs & RTA_DST == 0
				|| ptr->rtm_addrs & RTA_GATEWAY == 0
				|| ptr->rtm_addrs & RTA_NETMASK == 0)
			{
				ec = boost::asio::error::operation_not_supported;
				return std::vector<ip_route>();
			}
			if (ptr->rtm_msglen > len - ((char*)ptr - ((char*)&m.m_rtm)))
			{
				ec = boost::asio::error::operation_not_supported;
				return std::vector<ip_route>();
			}
			int min_len = sizeof(rt_msghdr) + 2 * sizeof(sockaddr_in);
			if (m.m_rtm.rtm_msglen < min_len)
			{
				ec = boost::asio::error::operation_not_supported;
				return std::vector<ip_route>();
			}

			ip_route r;
			// destination
			char* p = m.buf;
			sockaddr_in* sin = (sockaddr_in*)p;
			r.destination = sockaddr_to_address((sockaddr*)p);

			// gateway
			p += sin->sin_len;
			sin = (sockaddr_in*)p;
			r.gateway = sockaddr_to_address((sockaddr*)p);

			// netmask
			p += sin->sin_len;
			sin = (sockaddr_in*)p;
			r.netmask = sockaddr_to_address((sockaddr*)p);
			ret.push_back(r);
		}
		close(s);
*/
	int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0};

	size_t needed = 0;
#ifdef TORRENT_OS2
	if (__libsocket_sysctl(mib, 6, 0, &needed, 0, 0) < 0)
#else
	if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
#endif
	{
		ec = error_code(errno, boost::asio::error::system_category);
		return std::vector<ip_route>();
	}

	if (needed <= 0)
	{
		return std::vector<ip_route>();
	}

	boost::scoped_array<char> buf(new (std::nothrow) char[needed]);
	if (buf.get() == 0)
	{
		ec = boost::asio::error::no_memory;
		return std::vector<ip_route>();
	}

#ifdef TORRENT_OS2
	if (__libsocket_sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0)
#else
	if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0)
#endif
	{
		ec = error_code(errno, boost::asio::error::system_category);
		return std::vector<ip_route>();
	}

	char* end = buf.get() + needed;

	int s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0)
	{
		ec = error_code(errno, boost::asio::error::system_category);
		return std::vector<ip_route>();
	}
	rt_msghdr* rtm;
	for (char* next = buf.get(); next < end; next += rtm->rtm_msglen)
	{
		rtm = reinterpret_cast<rt_msghdr*>(next);
		if (rtm->rtm_version != RTM_VERSION)
			continue;

		ip_route r;
		if (parse_route(s, rtm, &r)) ret.push_back(r);
	}
	close(s);

#elif TORRENT_USE_GETIPFORWARDTABLE
/*
	move this to enum_net_interfaces
		// Load Iphlpapi library
		HMODULE iphlp = LoadLibraryA("Iphlpapi.dll");
		if (!iphlp)
		{
			ec = boost::asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		// Get GetAdaptersInfo() pointer
		typedef DWORD (WINAPI *GetAdaptersInfo_t)(PIP_ADAPTER_INFO, PULONG);
		GetAdaptersInfo_t GetAdaptersInfo = (GetAdaptersInfo_t)GetProcAddress(iphlp, "GetAdaptersInfo");
		if (!GetAdaptersInfo)
		{
			FreeLibrary(iphlp);
			ec = boost::asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		PIP_ADAPTER_INFO adapter_info = 0;
		ULONG out_buf_size = 0;
		if (GetAdaptersInfo(adapter_info, &out_buf_size) != ERROR_BUFFER_OVERFLOW)
		{
			FreeLibrary(iphlp);
			ec = boost::asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		adapter_info = (IP_ADAPTER_INFO*)malloc(out_buf_size);
		if (!adapter_info)
		{
			FreeLibrary(iphlp);
			ec = boost::asio::error::no_memory;
			return std::vector<ip_route>();
		}

		if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR)
		{
			for (PIP_ADAPTER_INFO adapter = adapter_info;
				adapter != 0; adapter = adapter->Next)
			{

				ip_route r;
				r.destination = address::from_string(adapter->IpAddressList.IpAddress.String, ec);
				r.gateway = address::from_string(adapter->GatewayList.IpAddress.String, ec);
				r.netmask = address::from_string(adapter->IpAddressList.IpMask.String, ec);
				strncpy(r.name, adapter->AdapterName, sizeof(r.name));

				if (ec)
				{
					ec = error_code();
					continue;
				}
				ret.push_back(r);
			}
		}

		// Free memory
		free(adapter_info);
		FreeLibrary(iphlp);
*/

		// Load Iphlpapi library
		HMODULE iphlp = LoadLibraryA("Iphlpapi.dll");
		if (!iphlp)
		{
			ec = boost::asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		typedef DWORD (WINAPI *GetIfEntry_t)(PMIB_IFROW pIfRow);
		GetIfEntry_t GetIfEntry = (GetIfEntry_t)GetProcAddress(iphlp, "GetIfEntry");
		if (!GetIfEntry)
		{
			ec = boost::asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

#if _WIN32_WINNT >= 0x0600
		typedef DWORD (WINAPI *GetIpForwardTable2_t)(
			ADDRESS_FAMILY, PMIB_IPFORWARD_TABLE2*);
		typedef void (WINAPI *FreeMibTable_t)(PVOID Memory);

		GetIpForwardTable2_t GetIpForwardTable2 = (GetIpForwardTable2_t)GetProcAddress(
			iphlp, "GetIpForwardTable2");
		FreeMibTable_t FreeMibTable = (FreeMibTable_t)GetProcAddress(
			iphlp, "FreeMibTable");
		if (GetIpForwardTable2 && FreeMibTable)
		{
			MIB_IPFORWARD_TABLE2* routes = NULL;
			int res = GetIpForwardTable2(AF_UNSPEC, &routes);
			if (res == NO_ERROR)
			{
				for (int i = 0; i < routes->NumEntries; ++i)
				{
					ip_route r;
					r.gateway = sockaddr_to_address((const sockaddr*)&routes->Table[i].NextHop);
					r.destination = sockaddr_to_address(
						(const sockaddr*)&routes->Table[i].DestinationPrefix.Prefix);
					r.netmask = build_netmask(routes->Table[i].SitePrefixLength
						, routes->Table[i].DestinationPrefix.Prefix.si_family);
					MIB_IFROW ifentry;
					ifentry.dwIndex = routes->Table[i].InterfaceIndex;
					if (GetIfEntry(&ifentry) == NO_ERROR)
					{
						wcstombs(r.name, ifentry.wszName, sizeof(r.name));
						r.mtu = ifentry.dwMtu;
						ret.push_back(r);
					}
				}
			}
			if (routes) FreeMibTable(routes);
			FreeLibrary(iphlp);
			return ret;
		}
#endif

		// Get GetIpForwardTable() pointer
		typedef DWORD (WINAPI *GetIpForwardTable_t)(PMIB_IPFORWARDTABLE pIpForwardTable,PULONG pdwSize,BOOL bOrder);

		GetIpForwardTable_t GetIpForwardTable = (GetIpForwardTable_t)GetProcAddress(
			iphlp, "GetIpForwardTable");
		if (!GetIpForwardTable)
		{
			FreeLibrary(iphlp);
			ec = boost::asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		MIB_IPFORWARDTABLE* routes = NULL;
		ULONG out_buf_size = 0;
		if (GetIpForwardTable(routes, &out_buf_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
		{
			FreeLibrary(iphlp);
			ec = boost::asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		routes = (MIB_IPFORWARDTABLE*)malloc(out_buf_size);
		if (!routes)
		{
			FreeLibrary(iphlp);
			ec = boost::asio::error::no_memory;
			return std::vector<ip_route>();
		}

		if (GetIpForwardTable(routes, &out_buf_size, FALSE) == NO_ERROR)
		{
			for (int i = 0; i < routes->dwNumEntries; ++i)
			{
				ip_route r;
				r.destination = inaddr_to_address((in_addr const*)&routes->table[i].dwForwardDest);
				r.netmask = inaddr_to_address((in_addr const*)&routes->table[i].dwForwardMask);
				r.gateway = inaddr_to_address((in_addr const*)&routes->table[i].dwForwardNextHop);
				MIB_IFROW ifentry;
				ifentry.dwIndex = routes->table[i].dwForwardIfIndex;
				if (GetIfEntry(&ifentry) == NO_ERROR)
				{
					wcstombs(r.name, ifentry.wszName, sizeof(r.name));
					r.name[sizeof(r.name)-1] = 0;
					r.mtu = ifentry.dwMtu;
					ret.push_back(r);
				}
			}
		}

		// Free memory
		free(routes);
		FreeLibrary(iphlp);
#elif TORRENT_USE_NETLINK
		enum { BUFSIZE = 8192 };

		int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE);
		if (sock < 0)
		{
			ec = error_code(errno, boost::asio::error::system_category);
			return std::vector<ip_route>();
		}

		int seq = 0;

		char msg[BUFSIZE];
		memset(msg, 0, BUFSIZE);
		nlmsghdr* nl_msg = (nlmsghdr*)msg;

		nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg));
		nl_msg->nlmsg_type = RTM_GETROUTE;
		nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
		nl_msg->nlmsg_seq = seq++;
		nl_msg->nlmsg_pid = getpid();

		if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0)
		{
			ec = error_code(errno, boost::asio::error::system_category);
			close(sock);
			return std::vector<ip_route>();
		}

		int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid());
		if (len < 0)
		{
			ec = error_code(errno, boost::asio::error::system_category);
			close(sock);
			return std::vector<ip_route>();
		}

		int s = socket(AF_INET, SOCK_DGRAM, 0);
		if (s < 0)
		{
			ec = error_code(errno, boost::asio::error::system_category);
			return std::vector<ip_route>();
		}
		for (; NLMSG_OK(nl_msg, len); nl_msg = NLMSG_NEXT(nl_msg, len))
		{
			ip_route r;
			if (parse_route(s, nl_msg, &r)) ret.push_back(r);
		}
		close(s);
		close(sock);

#endif
		return ret;
	}
Пример #15
0
	bool ip_voter::cast_vote(address const& ip
		, int source_type, address const& source)
	{
		if (is_any(ip)) return false;
		if (is_local(ip)) return false;
		if (is_loopback(ip)) return false;

		// don't trust source that aren't connected to us
		// on a different address family than the external
		// IP they claim we have
		if (ip.is_v4() != source.is_v4()) return false;

		// this is the key to use for the bloom filters
		// it represents the identity of the voter
		sha1_hash k;
		hash_address(source, k);

		// do we already have an entry for this external IP?
		std::vector<external_ip_t>::iterator i = std::find_if(m_external_addresses.begin()
			, m_external_addresses.end(), boost::bind(&external_ip_t::addr, _1) == ip);

		if (i == m_external_addresses.end())
		{
			// each IP only gets to add a new IP once
			if (m_external_address_voters.find(k)) return maybe_rotate();
		
			if (m_external_addresses.size() > 40)
			{
				if (random() % 100 < 50)
					return maybe_rotate();

				// use stable sort here to maintain the fifo-order
				// of the entries with the same number of votes
				// this will sort in ascending order, i.e. the lowest
				// votes first. Also, the oldest are first, so this
				// is a sort of weighted LRU.
				std::stable_sort(m_external_addresses.begin(), m_external_addresses.end());

				// erase the last element, since it is one of the
				// ones with the fewest votes
				m_external_addresses.erase(m_external_addresses.end() - 1);
			}
			m_external_addresses.push_back(external_ip_t());
			i = m_external_addresses.end() - 1;
			i->addr = ip;
		}
		// add one more vote to this external IP
		if (!i->add_vote(k, source_type)) return maybe_rotate();
		++m_total_votes;
		
		if (m_valid_external) return maybe_rotate();

		i = std::min_element(m_external_addresses.begin(), m_external_addresses.end());
		TORRENT_ASSERT(i != m_external_addresses.end());

		if (i->addr == m_external_address) return maybe_rotate();

		if (m_external_address != address_v4())
		{
			// we have a temporary external address. As soon as we have
			// more than 25 votes, consider deciding which one to settle for
			return (m_total_votes >= 25) ? maybe_rotate() : false;
		}

		m_external_address = i->addr;

		return true;
	}
Пример #16
0
/*! 
 *  \brief     Parse from Client
 *  
 *  \author    Fimbulwinter Development Team
 *  \author    GreenBox
 *  \date      08/12/11
 *
 **/
int CharServer::parse_from_client(tcp_connection::pointer cl)
{
	CharSessionData *csd = ((CharSessionData *)cl->get_data());

	if (cl->flags.eof)
	{
		if (csd && csd->auth && auth_conn_ok)
		{
			WFIFOHEAD(auth_conn,6);
			WFIFOW(auth_conn,0) = INTER_CA_SET_ACC_OFF;
			WFIFOL(auth_conn,2) = csd->account_id;
			auth_conn->send_buffer(6);
		}

		set_char_offline(csd->account_id, -1);

		if (csd)
			delete csd;

		ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", cl->socket().remote_endpoint().address().to_string().c_str());
		cl->do_close();
		return 0;
	}

	while(RFIFOREST(cl) >= 2)
	{
		unsigned short cmd = RFIFOW(cl, 0);

#define FIFOSD_CHECK(rest) { if(RFIFOREST(cl) < rest) return 0; if (csd==NULL || !csd->auth) { cl->skip(rest); return 0; } }

		switch (cmd)
		{
		case HEADER_CH_SELECT_CHAR:
			FIFOSD_CHECK(3);
			{
				int slot = RFIFOB(cl,2);
				int char_id;
				CharData cd;

				cl->skip(3);

				{
					statement s = (database->prepare << "SELECT `char_id` FROM `char` WHERE `account_id`=:a AND `char_num`=:s",
						use(csd->account_id), use(slot), into(char_id));

					s.execute(true);

					if (s.get_affected_rows() <= 0)
					{
						WFIFOPACKET(cl, spacket, HC_REFUSE_ENTER);
						spacket->error_code = 0;
						cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_ENTER));
					}
				}

				chars->load_char(char_id, cd, true);

				int server = -1;
				if (map_to_zone.count(cd.last_point.map))
					server = map_to_zone[cd.last_point.map];

				if (server < 0)
				{
					// TODO: Find for major city

					WFIFOPACKET(cl, spacket, SC_NOTIFY_BAN);
					spacket->error_code = 1;
					cl->send_buffer(sizeof(struct PACKET_SC_NOTIFY_BAN));
					break;
				}

				auth_nodes[csd->account_id].sex = csd->sex;
				auth_nodes[csd->account_id].char_id = char_id;
				auth_nodes[csd->account_id].gmlevel = csd->gmlevel;
				auth_nodes[csd->account_id].login_id1 = csd->login_id1;
				auth_nodes[csd->account_id].login_id2 = csd->login_id2;
				auth_nodes[csd->account_id].expiration_time = csd->expiration_time;

				WFIFOPACKET(cl, spacket, HC_NOTIFY_ZONESVR);
				spacket->char_id = char_id;
				maps.copy_map_name_ext((char*)spacket->map_name, cd.last_point.map);
				spacket->addr.ip = htonl(servers[server].addr.to_ulong());
				spacket->addr.port = servers[server].port;
				cl->send_buffer(sizeof(struct PACKET_HC_NOTIFY_ZONESVR));
			}
			break;

		case HEADER_CH_REQUEST_DEL_TIMER:
			FIFOSD_CHECK(6);
			delete2_req(cl, csd);
			cl->skip(6);
			break;

		case HEADER_CH_ACCEPT_DEL_REQ:
			FIFOSD_CHECK(12);
			delete2_accept(cl, csd);
			cl->skip(6);
			break;

		case HEADER_CH_CANCEL_DEL_REQ:
			FIFOSD_CHECK(6);
			delete2_cancel(cl, csd);
			cl->skip(6);
			break;

		case HEADER_CH_DELETE_CHAR:
		case HEADER_CH_DELETE_CHAR2:
			if (cmd == HEADER_CH_DELETE_CHAR) FIFOSD_CHECK(sizeof(struct PACKET_CH_DELETE_CHAR));
			if (cmd == HEADER_CH_DELETE_CHAR2) FIFOSD_CHECK(sizeof(struct PACKET_CH_DELETE_CHAR2));
			{
				int cid = RFIFOL(cl,2);
				char email[40];
				memcpy(email, RFIFOP(cl,6), 40);

				cl->skip((cmd == HEADER_CH_DELETE_CHAR) ? sizeof(struct PACKET_CH_DELETE_CHAR) : sizeof(struct PACKET_CH_DELETE_CHAR2));

				if (_strcmpi(email, csd->email) != 0 && (strcmp("*****@*****.**", csd->email) || (strcmp("*****@*****.**", email) && strcmp("", email))))
				{
					WFIFOPACKET(cl, spacket, HC_REFUSE_DELETECHAR); 
					spacket->error_code = 0;
					cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_DELETECHAR));
					break;
				}

				bool found = false;
				int i, ch;
				for (i = 0; i < MAX_CHARS; i++)
				{
					if (csd->found_char[i] == cid)
					{
						found = true;
						break;
					}
				}

				if (!found)
				{
					WFIFOPACKET(cl, spacket, HC_REFUSE_DELETECHAR); 
					spacket->error_code = 0;
					cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_DELETECHAR));
					break;
				}
				else
				{
					for(ch = i; ch < MAX_CHARS - 1; ch++)
						csd->found_char[ch] = csd->found_char[ch+1];

					csd->found_char[MAX_CHARS - 1] = -1;

					if (!chars->delete_char(cid))
					{
						WFIFOPACKET(cl, spacket, HC_REFUSE_DELETECHAR); 
						spacket->error_code = 0;
						cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_DELETECHAR));
						break;
					}

					WFIFOPACKET(cl, spacket, HC_ACCEPT_DELETECHAR);
					cl->send_buffer(sizeof(struct PACKET_HC_ACCEPT_DELETECHAR));
				}
			}
			break;

		case HEADER_CH_MAKE_CHAR:
			FIFOSD_CHECK(sizeof(struct PACKET_CH_MAKE_CHAR));
			{
				TYPECAST_PACKET(RFIFOP(cl,0),rpacket,CH_MAKE_CHAR);

				// TODO: Check create char disabled
				int i = create_char(csd, (char*)rpacket->name,rpacket->str,rpacket->agi,rpacket->vit,rpacket->int_,rpacket->dex,rpacket->luk,rpacket->char_slot,rpacket->head_color,rpacket->head_style);

				//'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3)
				if (i < 0)
				{
					WFIFOPACKET(cl, spacket, HC_REFUSE_MAKECHAR);

					switch (i) {
					case -1: spacket->error_code = 0x00; break;
					case -2: spacket->error_code = 0xFF; break;
					case -3: spacket->error_code = 0x01; break;
					}

					cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_MAKECHAR));
				}
				else
				{
					// retrieve data
					CharData char_dat;
					memset(&char_dat, 0, sizeof(CharData));
					chars->load_char(i, char_dat, false); //Only the short data is needed.

					// send to player
					WFIFOPACKET(cl, spacket, HC_ACCEPT_MAKECHAR);

					char_to_buf(&spacket->charinfo, &char_dat);

					cl->send_buffer(sizeof(struct PACKET_HC_ACCEPT_MAKECHAR));

					// add new entry to the chars list
					for (int n = 0; n < MAX_CHARS; n++)
					{
						if(csd->found_char[n] == -1)
							csd->found_char[n] = i; // the char_id of the new char
					}
				}
				cl->skip(sizeof(struct PACKET_CH_MAKE_CHAR));
			}
			break;

		case HEADER_CH_ENTER_CHECKBOT:
			FIFOSD_CHECK(sizeof(struct PACKET_CH_ENTER_CHECKBOT));
			{
				WFIFOPACKET(cl, spacket, HC_CHECKBOT_RESULT);
				spacket->packet_len = sizeof(struct PACKET_HC_CHECKBOT_RESULT);
				spacket->result = 1;
				cl->send_buffer(spacket->packet_len);
				cl->skip(TYPECAST_PACKET_ONCE(RFIFOP(cl,0), CH_ENTER_CHECKBOT)->packet_len);
			}
			break;

		case HEADER_CH_CHECKBOT:
			FIFOSD_CHECK(sizeof(struct PACKET_CH_CHECKBOT));
			{
				WFIFOPACKET(cl, spacket, HC_CHECKBOT_RESULT);
				spacket->packet_len = sizeof(struct PACKET_HC_CHECKBOT_RESULT);
				spacket->result = 1;
				cl->send_buffer(spacket->packet_len);
				cl->skip(TYPECAST_PACKET_ONCE(RFIFOP(cl,0), CH_CHECKBOT)->packet_len);
			}
			break;

		case HEADER_CH_ENTER:
			if(RFIFOREST(cl) < sizeof(struct PACKET_CH_ENTER))
				return 0;
			{
				int account_id = RFIFOL(cl,2);
				unsigned int login_id1 = RFIFOL(cl,6);
				unsigned int login_id2 = RFIFOL(cl,10);
				char sex = RFIFOB(cl,16);
				cl->skip(sizeof(struct PACKET_CH_ENTER));

				if (csd)
				{
					break;
				}

				csd = new CharSessionData();
				csd->account_id = account_id;
				csd->login_id1 = login_id1;
				csd->login_id2 = login_id2;
				csd->sex = sex;
				csd->auth = false;
				csd->cl = cl;
				cl->set_data((char*)csd);

				WFIFOHEAD(cl, 4);
				WFIFOL(cl,0) = account_id;
				cl->send_buffer(4);

				if (auth_nodes.count(account_id) && 
					auth_nodes[account_id].login_id1  == login_id1 &&
					auth_nodes[account_id].login_id2  == login_id2)
				{
					auth_nodes.erase(account_id);
					auth_ok(cl, csd);
				}
				else
				{
					if (auth_conn_ok)
					{
						WFIFOHEAD(auth_conn,19);
						WFIFOW(auth_conn,0) = INTER_CA_AUTH;
						WFIFOL(auth_conn,2) = csd->account_id;
						WFIFOL(auth_conn,6) = csd->login_id1;
						WFIFOL(auth_conn,10) = csd->login_id2;
						WFIFOB(auth_conn,14) = csd->sex;
						WFIFOL(auth_conn,15) = cl->tag();
						auth_conn->send_buffer(19);
					}
					else
					{
						WFIFOPACKET(cl, spacket, HC_REFUSE_ENTER);
						spacket->error_code = 0;
						cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_ENTER));
					}
				}
			}
			break;

		case HEADER_PING:
			if (RFIFOREST(cl) < sizeof(PACKET_PING))
				return 0;
			cl->skip(sizeof(PACKET_PING));
			break;

		case INTER_ZC_LOGIN:
			if (RFIFOREST(cl) < 60)
				return 0;
			{
				char *user = (char*)RFIFOP(cl, 2);
				char *pass = (char*)RFIFOP(cl, 26);

				if (strcmp(user, config.inter_login_user.c_str()) || strcmp(pass, config.inter_login_pass.c_str()))
				{
					WFIFOHEAD(cl, 3);
					WFIFOW(cl, 0) = INTER_CZ_LOGIN_REPLY;
					WFIFOB(cl, 2) = 1;
					cl->send_buffer(3);
				}
				else
				{
					int id = cl->tag();
					servers[id].cl = cl;
					servers[id].addr = address_v4(ntohl(RFIFOL(cl, 54)));
					servers[id].port = ntohs(RFIFOW(cl, 58));
					servers[id].users = 0;
					
					cl->set_parser(&CharServer::parse_from_zone);
					cl->flags.server = 1;
					cl->realloc_fifo(FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);

					WFIFOHEAD(cl, 3);
					WFIFOW(cl, 0) = INTER_CZ_LOGIN_REPLY;
					WFIFOB(cl, 2) = 0;
					cl->send_buffer(3);
				}

				cl->skip(60);
			}
			break;

		default:
			ShowWarning("Unknown packet 0x%04x sent from %s, closing connection.\n", cmd, cl->socket().remote_endpoint().address().to_string().c_str());
			cl->set_eof();
			return 0;
		}
	}

	return 0;
}
Пример #17
0
		static address loopback()
		{
			return address_v4(0x7F000001);
		}
Пример #18
0
		address read_v4_address(InIt& in)
		{
			unsigned long ip = read_uint32(in);
			return address_v4(ip);
		}
Пример #19
0
		operator address() const
		{
			if (v4) return address(address_v4(addr.v4));
			else return address(address_v6(addr.v6));
		}
 /// Obtain an address object that represents the loopback address.
 static address_v4 loopback()
 {
   return address_v4(static_cast<unsigned long>(INADDR_LOOPBACK));
 }
Пример #21
0
		static address any() { return address_v4(); }
Пример #22
0
		address read_v4_address(InIt&& in)
		{
			std::uint32_t const ip = read_uint32(in);
			return address_v4(ip);
		}
Пример #23
0
bool rpc_manager::incoming(msg const& m, node_id* id)
{
	INVARIANT_CHECK;

	if (m_destructing) return false;

	// we only deal with replies, not queries
	TORRENT_ASSERT(m.message.dict_find_string_value("y") == "r");

	// 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");

	std::string::const_iterator i = transaction_id.begin();	
	int tid = transaction_id.size() != 2 ? -1 : io::read_uint16(i);

	observer_ptr o;

	for (transactions_t::iterator i = m_transactions.begin()
		, end(m_transactions.end()); i != end; ++i)
	{
		TORRENT_ASSERT(*i);
		if ((*i)->transaction_id() != tid) continue;
		if (m.addr.address() != (*i)->target_addr()) continue;
		o = *i;
		m_transactions.erase(i);
		break;
	}

	if (!o)
	{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
		TORRENT_LOG(rpc) << "Reply with invalid transaction id size: " 
			<< transaction_id.size() << " from " << m.addr;
#endif
		entry e;
		incoming_error(e, "invalid transaction id");
		m_send(m_userdata, e, m.addr, 0);
		return false;
	}

#ifdef TORRENT_DHT_VERBOSE_LOGGING
	std::ofstream reply_stats("round_trip_ms.log", std::ios::app);
	reply_stats << m.addr << "\t" << total_milliseconds(time_now_hires() - o->sent())
		<< std::endl;
#endif

	lazy_entry const* ret_ent = m.message.dict_find_dict("r");
	if (ret_ent == 0)
	{
		entry e;
		incoming_error(e, "missing 'r' key");
		m_send(m_userdata, e, m.addr, 0);
		return false;
	}

	lazy_entry const* node_id_ent = ret_ent->dict_find_string("id");
	if (node_id_ent == 0 || node_id_ent->string_length() != 20)
	{
		entry e;
		incoming_error(e, "missing 'id' key");
		m_send(m_userdata, e, m.addr, 0);
		return false;
	}

	lazy_entry const* ext_ip = ret_ent->dict_find_string("ip");
	if (ext_ip && ext_ip->string_length() == 4)
	{
		// this node claims we use the wrong node-ID!
		address_v4::bytes_type b;
		memcpy(&b[0], ext_ip->string_ptr(), 4);
		m_ext_ip(address_v4(b), aux::session_impl::source_dht, m.addr.address());
	}
#if TORRENT_USE_IPV6
	else if (ext_ip && ext_ip->string_length() == 16)
	{
		// this node claims we use the wrong node-ID!
		address_v6::bytes_type b;
		memcpy(&b[0], ext_ip->string_ptr(), 16);
		m_ext_ip(address_v6(b), aux::session_impl::source_dht, m.addr.address());
	}
#endif

#ifdef TORRENT_DHT_VERBOSE_LOGGING
	TORRENT_LOG(rpc) << "[" << o->m_algorithm.get() << "] Reply with transaction id: " 
		<< tid << " from " << m.addr;
#endif
	o->reply(m);
	*id = node_id(node_id_ent->string_ptr());

	// 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);
}
Пример #24
0
		static address broadcast()
		{
			return address_v4(0xFFFFFFFF);
		}
/**
 * @relates address_v4
 */
inline address_v4 make_address_v4(const address_v4::bytes_type& bytes)
{
  return address_v4(bytes);
}
 /// Obtain an address object that represents any address.
 static address_v4 any()
 {
   return address_v4(static_cast<unsigned long>(INADDR_ANY));
 }
/**
 * @relates address_v4
 */
inline address_v4 make_address_v4(address_v4::uint_type addr)
{
  return address_v4(addr);
}
 /// Obtain an address object that represents the broadcast address.
 static address_v4 broadcast()
 {
   return address_v4(static_cast<unsigned long>(INADDR_BROADCAST));
 }
Пример #29
0
std::pair<address,int> ipport_from_string(const std::string&ipPortStr)
{
	std::string ipStr,portStr;
	const size_t first=ipPortStr.find_first_of(':');
	const size_t last=(first==std::string::npos
		?std::string::npos : ipPortStr.find_last_of(':',first+1)
		);
	bool v6=false;
	if (first!=std::string::npos)
	{
		const size_t posR=ipPortStr.find_first_of(']');
		const size_t posL=ipPortStr.find_first_of('[');
		if (last!=first
			||posR!=std::string::npos
			||posL!=std::string::npos
			)//is ipv6?
		{
			if (posR!=std::string::npos&&posL==std::string::npos
				||posR==std::string::npos&&posL!=std::string::npos
				||posL>posR
				)
			{
				return std::pair<address,int>(address(),0);//error format
			}
			v6=true;
			if (posR!=std::string::npos)//[ip]:port
			{
				BOOST_ASSERT(posL!=std::string::npos&&posR>posL);
				ipStr=ipPortStr.substr(posL+1,posR-posL-1);
				if (last>posR&&last!=std::string::npos&&last+1<ipPortStr.size())
					portStr=ipPortStr.substr(last+1);
			}
			else// only ip
			{
				ipStr=ipPortStr;
			}
		}
		else//is ipv4?
		{
			ipStr=ipPortStr.substr(0,last);
			if (last+1<ipPortStr.size())
				portStr=ipPortStr.substr(last+1);
		}
	}
	else
	{
		const size_t pos=ipPortStr.find_first_of(']');
		if (pos!=std::string::npos)//[]
		{
			v6=true;
			if (ipPortStr[0]=='[')
				ipStr=ipPortStr.substr(1,pos);
			else
				return std::pair<address,int>(address(),0);//error format
			if (pos+1<ipPortStr.size())
				portStr=ipPortStr.substr(pos+1);
			if (boost::iequals(ipStr,"localhost")||boost::iequals(ipStr,"loopback"))
			{
				ipStr="::1";
			}
		}
		else// only ip
		{
			ipStr=ipPortStr;
		}
		ipStr=ipPortStr;
	}

	error_code ec;
	if (ipStr.empty())
	{
		if (v6)
			ipStr=address_v6().to_string(ec);
		else
			ipStr=address_v4().to_string(ec);
	}
	if (boost::iequals(ipStr,"localhost")||boost::iequals(ipStr,"loopback"))
	{
		if (v6)
			ipStr=address_v6::loopback().to_string(ec);
		else
			ipStr=address_v4::loopback().to_string(ec);
	}

	int port=0;
	if (!portStr.empty())
		port=atoi(portStr.c_str());
	if (v6)
		return std::pair<address,int>(address_v6::from_string(ipStr,ec),port);
	else
		return std::pair<address,int>(address_v4::from_string(ipStr,ec),port);
}