예제 #1
0
파일: net_ws.cpp 프로젝트: omertelli/rehlds
/* <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;
}
예제 #2
0
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;
}