コード例 #1
0
void C4Network2Client::AddAddrFromPuncher(const C4NetIO::addr_t &addr)
{
	AddAddr(C4Network2Address(addr, P_UDP), true);
	// If the outside port matches the inside port, there is no port translation and the
	// TCP address will probably work as well.
	if (addr.GetPort() == Config.Network.PortUDP && Config.Network.PortTCP > 0)
	{
		auto tcpAddr = addr;
		tcpAddr.SetPort(Config.Network.PortTCP);
		AddAddr(C4Network2Address(tcpAddr, P_TCP), true);
	}
	// Save IPv6 address for TCP simultaneous connect.
	if (addr.GetFamily() == C4NetIO::addr_t::IPv6)
		IPv6AddrFromPuncher = addr;
}
コード例 #2
0
ファイル: C4Network2Client.cpp プロジェクト: ev1313/yaC
void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP) {
  // set up address struct
  sockaddr_in addr;
  ZeroMem(&addr, sizeof addr);
  addr.sin_family = AF_INET;

  // get local address(es)
  in_addr **ppAddr = NULL;
#ifdef HAVE_WINSOCK
  bool fGotWinSock = AcquireWinSock();
  if (fGotWinSock)
#endif
  {
    // get local host name
    char szLocalHostName[128 + 1];
    *szLocalHostName = '\0';
    ::gethostname(szLocalHostName, 128);
    // get hostent-struct
    hostent *ph = ::gethostbyname(szLocalHostName);
    // check type, get addr list
    if (ph)
      if (ph->h_addrtype != AF_INET)
        ph = NULL;
      else
        ppAddr = reinterpret_cast<in_addr **>(ph->h_addr_list);
  }

  // add address(es)
  for (;;) {
    if (iPortTCP >= 0) {
      addr.sin_port = htons(iPortTCP);
      AddAddr(C4Network2Address(addr, P_TCP), false);
    }
    if (iPortUDP >= 0) {
      addr.sin_port = htons(iPortUDP);
      AddAddr(C4Network2Address(addr, P_UDP), false);
    }
    // get next
    if (!ppAddr || !*ppAddr) break;
    addr.sin_addr = **ppAddr++;
  }

#ifdef HAVE_WINSOCK
  if (fGotWinSock) ReleaseWinSock();
#endif
}
コード例 #3
0
void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
{
	C4NetIO::addr_t addr;

	for (auto& ha : C4NetIO::GetLocalAddresses())
	{
		addr.SetAddress(ha);
		if (iPortTCP)
		{
			addr.SetPort(iPortTCP);
			AddAddr(C4Network2Address(addr, P_TCP), false);
		}
		if (iPortUDP)
		{
			addr.SetPort(iPortUDP);
			AddAddr(C4Network2Address(addr, P_UDP), false);
		}
		if (addr.GetScopeId())
			InterfaceIDs.insert(addr.GetScopeId());
	}
}
コード例 #4
0
bool C4Network2Client::DoConnectAttempt(C4Network2IO *pIO)
{
	// local?
	if (isLocal()) { iNextConnAttempt = 0; return true; }
	// msg and data connected? Nothing to do
	if (getMsgConn() != getDataConn()) { iNextConnAttempt = time(nullptr) + 10; return true; }
	// too early?
	if (iNextConnAttempt && iNextConnAttempt > time(nullptr)) return true;
	// find address to try
	int32_t iBestAddress = -1;
	for (int32_t i = 0; i < iAddrCnt; i++)
		// no connection for this protocol?
		if ((!pDataConn || Addr[i].getProtocol() != pDataConn->getProtocol()) &&
		    (!pMsgConn  || Addr[i].getProtocol() != pMsgConn->getProtocol()))
			// protocol available?
			if (pIO->getNetIO(Addr[i].getProtocol()))
				// new best address?
				if (iBestAddress < 0 || AddrAttempts[i] < AddrAttempts[iBestAddress])
					iBestAddress = i;
	// too many attempts or nothing found?
	if (iBestAddress < 0 || AddrAttempts[iBestAddress] > C4NetClientConnectAttempts)
		{ iNextConnAttempt = time(nullptr) + 10; return true; }
	// save attempt
	AddrAttempts[iBestAddress]++; iNextConnAttempt = time(nullptr) + C4NetClientConnectInterval;
	auto addr = Addr[iBestAddress].getAddr();

	// try TCP simultaneous open if the stars align right
	if (addr.GetFamily() == C4NetIO::addr_t::IPv6 && // address needs to be IPv6...
	    !addr.IsLocal() && !addr.IsPrivate() &&      // ...global unicast...
	    Addr[iBestAddress].getProtocol() == P_TCP && // ...TCP,
	    !TcpSimOpenSocket &&                         // there is no previous request,
	    pParent->GetLocal()->getID() < getID())      // and make sure that only one client per pair initiates a request.
	{
		DoTCPSimultaneousOpen(pIO, C4Network2Address());
	}

	std::set<int> interfaceIDs;
	if (addr.IsLocal())
	    interfaceIDs = Network.Clients.GetLocal()->getInterfaceIDs();
	else
	    interfaceIDs = {0};
	for (auto id : interfaceIDs)
	{
	    addr.SetScopeId(id);
	    // log
	    LogSilentF("Network: connecting client %s on %s...", getName(), addr.ToString().getData());
	    // connect
	    if (pIO->Connect(addr, Addr[iBestAddress].getProtocol(), pClient->getCore()))
		return true;
	}
	return false;
}
コード例 #5
0
ファイル: C4Network2IO.cpp プロジェクト: 772/openclonk
void C4Network2IO::OnPunch(C4NetIO::addr_t addr)
{
    // Sanity check
    assert (addr.sin_family == AF_INET);
    if (addr.sin_family != AF_INET)
        return;
    ZeroMem(addr.sin_zero, sizeof(addr.sin_zero));
    // Add for local client
    C4Network2Client *pLocal = ::Network.Clients.GetLocal();
    if (pLocal)
        if (pLocal->AddAddr(C4Network2Address(addr, P_UDP), true))
            ::Network.InvalidateReference();
}
コード例 #6
0
ファイル: C4Network2Client.cpp プロジェクト: 772/openclonk
void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
{
	// set up address struct
	sockaddr_in addr; ZeroMem(&addr, sizeof addr);
	addr.sin_family = AF_INET;

	// get local address(es)
	in_addr **ppAddr = NULL;
#ifdef HAVE_WINSOCK
	bool fGotWinSock = AcquireWinSock();
	if (fGotWinSock)
	{
		// get local host name
		char szLocalHostName[128+1]; *szLocalHostName = '\0';
		::gethostname(szLocalHostName, 128);
		// get hostent-struct
		hostent *ph = ::gethostbyname(szLocalHostName);
		// check type, get addr list
		if (ph)
		{
			if (ph->h_addrtype != AF_INET)
				ph = NULL;
			else
				ppAddr = reinterpret_cast<in_addr **>(ph->h_addr_list);
		}
	}
#else
	std::vector<in_addr*> addr_vec;
	struct ifaddrs* addrs;
	getifaddrs(&addrs);
	for(struct ifaddrs* addr = addrs; addr != NULL; addr = addr->ifa_next)
	{
		struct sockaddr* ad = addr->ifa_addr;
		if(ad == NULL) continue;

		if(ad->sa_family == AF_INET && (~addr->ifa_flags & IFF_LOOPBACK)) // Choose only non-loopback IPv4 devices
			addr_vec.push_back(&reinterpret_cast<sockaddr_in*>(ad)->sin_addr);
	}

	addr_vec.push_back(NULL);
	ppAddr = &addr_vec[0];
#endif

	// add address(es)
	for (;;)
	{
		if (iPortTCP >= 0)
		{
			addr.sin_port = htons(iPortTCP);
			AddAddr(C4Network2Address(addr, P_TCP), false);
		}
		if (iPortUDP >= 0)
		{
			addr.sin_port = htons(iPortUDP);
			AddAddr(C4Network2Address(addr, P_UDP), false);
		}
		// get next
		if (!ppAddr || !*ppAddr) break;
		addr.sin_addr = **ppAddr++;
	}

#ifdef HAVE_WINSOCK
	if (fGotWinSock) ReleaseWinSock();
#else
	if(addrs) freeifaddrs(addrs);
#endif
}
コード例 #7
0
bool C4Network2Client::DoTCPSimultaneousOpen(class C4Network2IO *pIO, const C4Network2Address &addr)
{
	if (!pIO->getNetIO(P_TCP)) return false;

	// Did we already bind a socket?
	if (TcpSimOpenSocket)
	{
		LogSilentF("Network: connecting client %s on %s with TCP simultaneous open...", getName(), addr.getAddr().ToString().getData());
		return pIO->ConnectWithSocket(addr.getAddr(), addr.getProtocol(), pClient->getCore(), std::move(TcpSimOpenSocket));
	}
	else
	{
		// No - bind one, inform peer, and schedule a connection attempt.
		auto NetIOTCP = dynamic_cast<C4NetIOTCP*>(pIO->getNetIO(P_TCP));
		auto bindAddr = pParent->GetLocal()->IPv6AddrFromPuncher;
		// We need to know an address that works.
		if (bindAddr.IsNull()) return false;
		bindAddr.SetPort(0);
		TcpSimOpenSocket = NetIOTCP->Bind(bindAddr);
		auto boundAddr = TcpSimOpenSocket->GetAddress();
		LogSilentF("Network: %s TCP simultaneous open request for client %s from %s...", addr.isIPNull() ? "initiating" : "responding to",
				getName(), boundAddr.ToString().getData());
		// Send address we bound to to the client.
		if (!SendMsg(MkC4NetIOPacket(PID_TCPSimOpen, C4PacketTCPSimOpen(pParent->GetLocal()->getID(), C4Network2Address(boundAddr, P_TCP)))))
			return false;
		if (!addr.isIPNull())
		{
			// We need to delay the connection attempt a bit. Unfortunately,
			// waiting for the next tick would usually take way too much time.
			// Instead, we block the main thread for a very short time and hope
			// that noone notices...
			int ping = getMsgConn()->getLag();
			std::this_thread::sleep_for(std::chrono::milliseconds(std::min(ping / 2, 10)));
			DoTCPSimultaneousOpen(pIO, addr);
		}
		return true;
	}
}