/* <d455d> ../engine/net_ws.c:1700 */ int NET_IPSocket(char *net_interface, int port, qboolean multicast) { int newsocket; struct sockaddr_in address; qboolean _true = TRUE; int i = 1; int err; #ifdef _WIN32 if ((newsocket = CRehldsPlatformHolder::get()->socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) #else if ((newsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) #endif // _WIN32 { #ifdef _WIN32 err = CRehldsPlatformHolder::get()->WSAGetLastError(); #else err = errno; #endif // _WIN32 if (err != WSAEAFNOSUPPORT) Con_Printf("WARNING: UDP_OpenSocket: port: %d socket: %s", port, NET_ErrorString(err)); return 0; } #ifdef _WIN32 if (CRehldsPlatformHolder::get()->ioctlsocket(newsocket, FIONBIO, (u_long *)&_true) == SOCKET_ERROR) #else if (SOCKET_FIONBIO(newsocket, _true) == SOCKET_ERROR) #endif // _WIN32 { #ifdef _WIN32 err = CRehldsPlatformHolder::get()->WSAGetLastError(); #else err = errno; #endif // _WIN32 Con_Printf("WARNING: UDP_OpenSocket: port: %d ioctl FIONBIO: %s\n", port, NET_ErrorString(err)); return 0; } #ifdef _WIN32 if (CRehldsPlatformHolder::get()->setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == SOCKET_ERROR) #else if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == SOCKET_ERROR) #endif { #ifdef _WIN32 err = CRehldsPlatformHolder::get()->WSAGetLastError(); #else err = errno; #endif // _WIN32 Con_Printf ("WARNING: UDP_OpenSocket: port: %d setsockopt SO_BROADCAST: %s\n", port, NET_ErrorString(err)); return 0; } if (COM_CheckParm("-reuse") || multicast) { #ifdef _WIN32 if (CRehldsPlatformHolder::get()->setsockopt(newsocket, SOL_SOCKET, SO_REUSEADDR, (char *)&_true, sizeof(qboolean)) == SOCKET_ERROR) #else if (setsockopt(newsocket, SOL_SOCKET, SO_REUSEADDR, (char *)&_true, sizeof(qboolean)) == SOCKET_ERROR) #endif // _WIN32 { #ifdef _WIN32 err = CRehldsPlatformHolder::get()->WSAGetLastError(); #else err = errno; #endif // _WIN32 Con_Printf ("WARNING: UDP_OpenSocket: port: %d setsockopt SO_REUSEADDR: %s\n", port, NET_ErrorString(err)); return 0; } } #ifndef _WIN32 if (COM_CheckParm("-tos")) { i = 16; Con_Printf("Enabling LOWDELAY TOS option\n"); if (setsockopt(newsocket, IPPROTO_IP, IP_TOS, (char *)&i, sizeof(i)) == SOCKET_ERROR) { err = errno; if (err != WSAENOPROTOOPT) Con_Printf("WARNING: UDP_OpenSocket: port: %d setsockopt IP_TOS: %s\n", port, NET_ErrorString(err)); return 0; } } #endif // _WIN32 if (net_interface && *net_interface && Q_stricmp(net_interface, "localhost")) NET_StringToSockaddr(net_interface, (sockaddr *)&address); else address.sin_addr.s_addr = INADDR_ANY; if (port == -1) address.sin_port = 0; else address.sin_port = htons((u_short)port); address.sin_family = AF_INET; #ifdef _WIN32 if (CRehldsPlatformHolder::get()->bind(newsocket, (struct sockaddr *)&address, sizeof(address)) == SOCKET_ERROR) #else if (bind(newsocket, (struct sockaddr *)&address, sizeof(address)) == SOCKET_ERROR) #endif // _WIN32 { #ifdef _WIN32 err = CRehldsPlatformHolder::get()->WSAGetLastError(); #else err = errno; #endif // _WIN32 Con_Printf("WARNING: UDP_OpenSocket: port: %d bind: %s\n", port, NET_ErrorString(err)); #ifdef _WIN32 CRehldsPlatformHolder::get()->closesocket(newsocket); #else SOCKET_CLOSE(newsocket); #endif // _WIN32 return 0; } i = COM_CheckParm("-loopback") != 0; #ifdef _WIN32 if (CRehldsPlatformHolder::get()->setsockopt(newsocket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&i, sizeof(i)) == SOCKET_ERROR) #else if (setsockopt(newsocket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&i, sizeof(i)) == SOCKET_ERROR) #endif // _WIN32 { #ifdef _WIN32 err = CRehldsPlatformHolder::get()->WSAGetLastError(); #else err = errno; #endif // _WIN32 Con_DPrintf("WARNING: UDP_OpenSocket: port %d setsockopt IP_MULTICAST_LOOP: %s\n", port, NET_ErrorString(err)); } return newsocket; }
bool NetSocket::Create(Network *network, int port, bool reuse, bool loopback) { sockaddr_in address; char _true = 1; uint32 i = 1; m_Network = network; m_System = network->GetSystem(); m_Channels.Init(); memset(m_Buffer, 0, sizeof(m_Buffer)); memset(&m_NetSplitPacket, 0, sizeof(m_NetSplitPacket)); if ((m_Socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { return false; } if (SOCKET_FIONBIO(m_Socket, i) == SOCKET_ERROR) { return false; } if (setsockopt(m_Socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == SOCKET_ERROR) { return false; } // resue if (reuse && setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, &_true, sizeof(_true)) == SOCKET_ERROR) { return false; } if (m_Network->m_IsMultihomed) { m_Network->GetLocalAddress()->ToSockadr((sockaddr *)&address); } else { address.sin_addr.s_addr = 0; } m_Port = port; address.sin_port = htons(port); address.sin_family = AF_INET; if (bind(m_Socket, (struct sockaddr *)&address, sizeof(address)) == SOCKET_ERROR) { SOCKET_CLOSE(m_Socket); return false; } // Time-To-Live (TTL) for Multicast Packets // As the values of the TTL field increase, routers will expand the number of hops they will forward a multicast packet. // To provide meaningful scope control, multicast routers enforce the following // "thresholds" on forwarding based on the TTL field: // // 0: restricted to the same host // 1: restricted to the same subnet // 32: restricted to the same site // 64: restricted to the same region // 128: restricted to the same continent // 255: unrestricted uint32 ttl = 32; char *ttlparam = m_System->CheckParam("-multicastttl"); if (ttlparam) { ttl = atoi(ttlparam); } if (setsockopt(m_Socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) == SOCKET_ERROR) { return false; } m_BytesOut = 0; m_BytesIn = 0; m_LastUpdateTime = 0; m_AvgBytesOut = 0; m_AvgBytesIn = 0; return true; }