Beispiel #1
0
// heartbeat master servers.
// send a message to the master every few minutes.
static void QRY_HeartbeatMasters(void)
{
	char		string[128];
	int			i, len;
	master_t	*m;
	time_t		current_time = time(NULL);
	char		buf[] = "xxx.xxx.xxx.xxx:xxxxx";

	// do we need heartbeat masters?
	if (!masters_heartbeat->integer)
		return;

	if (current_time < masters.last_heartbeat + QW_MASTER_HEARTBEAT_SECONDS)
		return; // not yet
	
	masters.last_heartbeat = current_time;
	masters.heartbeat_sequence++;
	snprintf(string, sizeof(string), "%c\n%i\n%i\n", S2M_HEARTBEAT, masters.heartbeat_sequence, FWD_peers_count());
	len = strlen(string);

	if (developer->integer > 1)
		Sys_DPrintf("heartbeat:\n%s\n", string);

	for (i = 0, m = masters.master; i < MAX_MASTERS; i++, m++)
	{
		if (m->state != ms_used)
			continue; // master slot not used
		
		Sys_DPrintf("heartbeat master: %s\n", NET_AdrToString(&m->addr, buf, sizeof(buf)));
		NET_SendPacket(net_socket, len, string, &m->addr);
	}
}
Beispiel #2
0
void SVC_QRY_ParseMasterReply(void)
{
    int				i, c;
	master_t		*m;
	int				ret = net_message.cursize;
	unsigned char	*answer = net_message.data; // not the smartest way, but why copy from one place to another...

	// no point to parse it, we do not query masters
	if (!masters_query->integer)
	{
		Sys_DPrintf("master server reply ignored\n");
		return;
	}

	Sys_DPrintf ("master server reply from %s:%d\n", inet_ntoa(net_from.sin_addr), (int)ntohs(net_from.sin_port));

	// is it reply from registered master server or someone trying to do some evil things?
	for (i = 0, m = masters.master; i < MAX_MASTERS; i++, m++)
	{
		if (m->state != ms_used)
			continue; // master slot not used

		if (NET_CompareAddress(&net_from, &m->addr))
		{
			// OK - it is reply from registered master server
			m->next_query = time(NULL) + QW_MASTER_QUERY_TIME; // delay next query for some time
			break;
		}
	}

	if (i >= MAX_MASTERS)
	{
		Sys_Printf("Reply from not registered master server\n");
		return;
	}

	Sys_DPrintf("master server returned %d bytes\n", ret);

	for (c = 0, i = 6; i + 5 < ret; i += 6, c++)
	{
		char ip[64];
		int port = 256 * (int)answer[i+4] + (int)answer[i+5];

		snprintf(ip, sizeof(ip), "%u.%u.%u.%u",
			(int)answer[i+0], (int)answer[i+1],
			(int)answer[i+2], (int)answer[i+3]);

		if (developer->integer > 1)
			Sys_DPrintf("SERVER: %4d %s:%d\n", c, ip, port);

		QRY_SV_new(ip, port, true);
	}
}
Beispiel #3
0
static server_t	*QRY_SV_new(const char *remote_host, int remote_port, qbool link)
{
	server_t			*sv;
	struct sockaddr_in	addr;

	if (QRY_SV_Count() >= MAX_SERVERS)
		return NULL;

	if (!NET_GetSockAddrIn_ByHostAndPort(&addr, remote_host, remote_port))
		return NULL; // failed to resolve host name?

	if ((sv = QRY_SV_ByAddr(&addr)))
		return NULL; // we already have such server on list

	if (QRY_FL_Filtered(&addr))
	{
		char buf[] = "xxx.xxx.xxx.xxx:xxxxx";
		Sys_DPrintf("filtered: %s\n", NET_AdrToString(&addr, buf, sizeof(buf)));
		return NULL; // filtered
	}

	sv_count++;

	sv = Sys_malloc(sizeof(*sv));
	sv->addr = addr;
	sv->ping = 0xFFFF; // mark as unreachable

	if (link)
	{
		sv->next = servers;
		servers = sv;
	}

	return sv;
}
Beispiel #4
0
// check if "masters" or "masters_query" cvar changed and do appropriate action
static void QRY_CheckMastersModified(void)
{
	char *mlist;

	// for fix issues with DNS and such force masters re-init time to time
	if (time(NULL) - masters.init_time > QW_MASTERS_FORCE_RE_INIT)
	{
		Sys_DPrintf("forcing masters re-init\n");
		masters_list->modified = true;
	}

	// "masters" and "masters_query" was not modified, do nothing
	if (!masters_list->modified && !masters_query->modified)
		return;

	// clear masters
	QRY_MastersInit();

	// add all masters
	for ( mlist = masters_list->string; (mlist = COM_Parse(mlist)); )
	{
		QRY_AddMaster(com_token);
	}

	masters_list->modified = masters_query->modified = false;
}
Beispiel #5
0
// query master servers
static void QRY_QueryMasters(void)
{
	int			i;
	master_t	*m;
	time_t		current_time = time(NULL);
	char		buf[] = "xxx.xxx.xxx.xxx:xxxxx";

	// do we need query masters?
	if (!masters_query->integer)
		return;

	for (i = 0, m = masters.master; i < MAX_MASTERS; i++, m++)
	{
		if (m->state != ms_used)
			continue; // master slot not used

		if (current_time <= m->next_query)
			continue; // not yet

		Sys_DPrintf("query master: %s\n", NET_AdrToString(&m->addr, buf, sizeof(buf)));
		
		NET_SendPacket(net_socket, sizeof(QW_MASTER_QUERY), QW_MASTER_QUERY, &m->addr);
		m->next_query = current_time + QW_MASTER_QUERY_TIME_SHORT; // delay next query for some time
	}
}
Beispiel #6
0
void QRY_SV_PingReply(void)
{
	server_t *sv = NULL;

	// ignore server ping reply since we do not query masters and can't keep server list up2date
	if (!masters_query->integer)
	{
		Sys_DPrintf("server reply ignored\n");
		return;
	}

	sv = QRY_SV_ByAddr(&net_from);

	if (sv)
	{
		double current = Sys_DoubleTime();
		double ping = current - sv->ping_sent_at;

		sv->ping = (int)max(0, 1000.0 * ping);
		sv->ping_reply_at = current;
		sv->reply = true;

//		Sys_Printf("ping <- %s:%d, %d\n", inet_ntoa(net_from.sin_addr), (int)ntohs(net_from.sin_port), sv->ping);
	}
	else
	{
//		Sys_Printf("ping <- %s:%d, not registered server\n", inet_ntoa(net_from.sin_addr), (int)ntohs(net_from.sin_port));
	}
}
Beispiel #7
0
Datei: net.c Projekt: deurk/qwfwd
/*
====================
NET_Init
====================
*/
void NET_Init (void)
{
	char *ip = (*ps.params.ip) ? ps.params.ip : "0.0.0.0";
	char port[64] = {0};

	snprintf(port, sizeof(port), "%d", 	ps.params.port ? ps.params.port : QWFWD_DEFAULT_PORT);

	if (*ps.params.ip) // if cmd line - force it, so we have priority over cfg
		net_ip	 = Cvar_FullSet("net_ip", ip, CVAR_NOSET);
	else
		net_ip	 = Cvar_Get("net_ip",	  ip, CVAR_NOSET);

	if (ps.params.port) // if cmd line - force it, so we have priority over cfg
		net_port = Cvar_FullSet("net_port",	port, CVAR_NOSET);
	else
		net_port = Cvar_Get("net_port",		port, CVAR_NOSET);

#ifdef _WIN32
	{
		WSADATA		winsockdata;

		if (WSAStartup(MAKEWORD (2, 1), &winsockdata))
			Sys_Error("WinSock initialization failed");
	}
#endif

	if ((net_socket = NET_UDP_OpenSocket(net_ip->string, net_port->integer, true)) == INVALID_SOCKET)
		Sys_Error("NET_Init: failed to initialize socket");

	// init the message buffer
	SZ_InitEx(&net_message, net_message_buffer, sizeof(net_message_buffer), false);

	Sys_DPrintf("UDP Initialized\n");
}
Beispiel #8
0
void dnLoadSnapshot( const snapshot_t *snapshot ) {
	Sys_DPrintf( "[DUKEMP] dnLoadSnapshot: loading snapshot\n" );	
	
	dnRestoreSnapshot( snapshot );
	resetinterpolations();
	show_shareware = 0;
	everyothertime = 0;
	resetmys();
	ready2send = 1;
	
//	waitforeverybody();
	
	resettimevars();
}
Beispiel #9
0
static void FWD_check_drop(void)
{
	peer_t *p, *next;

	for (p = peers; p; p = next)
	{
		next = p->next;

		if (p->ps != ps_drop)
			continue;

		Sys_DPrintf("peer %s:%d dropped\n", inet_ntoa(p->from.sin_addr), (int)ntohs(p->from.sin_port));
		FWD_peer_free(p, true); // NOTE: 'p' is not valid after this function, so we remember 'next' before this function
	}
}
Beispiel #10
0
static void QRY_FL_RemoveFilteredServers(void)
{
	int			i;
	server_t	*sv;

	for (i = 0; i < server_filter.count; i++)
	{
		if ((sv = QRY_SV_ByAddrEx(&server_filter.addr[i], true)))
		{
			char buf[] = "xxx.xxx.xxx.xxx:xxxxx";
			Sys_DPrintf("filtered: %s\n", NET_AdrToString(&sv->addr, buf, sizeof(buf)));
			QRY_SV_free(sv, true);
		}
	}
}
Beispiel #11
0
static void QRY_SV_PingServers(void)
{
	static int		idx;
	static double	last;

	double			current = Sys_DoubleTime(); // we need double time for ping measurement
	server_t		*sv;

	// do not ping servers since we do not query masters
	if (!masters_query->integer)
		return;

	if (!servers)
		return; // nothing to do

	if (current - last < QW_SERVER_RATE)
		return; // do not ping servers too fast

	last = current;

	idx = (int)max(0, idx);
	sv = QRY_SV_ByIndex(idx++);
	if (!sv)
		sv = QRY_SV_ByIndex(idx = 0); // can't find server by index, try with index 0

	if (!sv)
		return; // hm, should not be the case...

	// check for dead server
	if (!sv->reply && sv->ping_sent_at - sv->ping_reply_at > QW_SERVER_DEAD_TIME)
	{
		Sys_DPrintf("dead -> %s:%d\n", inet_ntoa(sv->addr.sin_addr), (int)ntohs(sv->addr.sin_port));

		QRY_SV_free(sv, true); // remove damn server, however master server may add it back...
		idx--; // step back index
		return;
	}

	if (sv->ping_sent_at && current - sv->ping_sent_at < QW_SERVER_MIN_PING_REQUEST_TIME)
		return; // do not spam server

	sv->ping_sent_at = current; // remember when we sent ping
	sv->reply = false; // reset reply flag

	NET_SendPacket(net_socket, sizeof(QW_SERVER_PING_QUERY)-1, QW_SERVER_PING_QUERY, &sv->addr);
//	Sys_Printf("ping(%3d) -> %s:%d\n", idx, inet_ntoa(sv->addr.sin_addr), (int)ntohs(sv->addr.sin_port));
}
Beispiel #12
0
int Net_GetPacket(cluster_t *cluster, netmsg_t *msg)
{
	int ret;
	socklen_t fromlen = sizeof (cluster->net_from);

	ClearNetMsg(msg);

	if (cluster->udpsocket == INVALID_SOCKET)
		return false;

	ret = recvfrom(cluster->udpsocket, (char *)msg->data, msg->maxsize, 0, (struct sockaddr *) &cluster->net_from, &fromlen);

	if (ret == -1)
	{
		if (qerrno == EWOULDBLOCK)
			return false;

		if (qerrno == EMSGSIZE)
		{
			Sys_Printf ("NET_GetPacket: Oversize packet from %s\n", inet_ntoa(cluster->net_from.sin_addr));
			return false;
		}

		if (qerrno == ECONNRESET)
		{
			Sys_DPrintf ("NET_GetPacket: Connection was forcibly closed by %s\n", inet_ntoa(cluster->net_from.sin_addr));
			return false;
		}

		Sys_Printf ("NET_GetPacket: recvfrom: (%i): %s\n", qerrno, strerror (qerrno));
		return false;
	}

	if (ret >= msg->maxsize)
	{
		Sys_Printf ("NET_GetPacket: Oversize packet from %s\n", inet_ntoa(cluster->net_from.sin_addr));
		return false;
	}

	msg->cursize = ret;
	msg->data[ret] = 0;

	return ret;
}
Beispiel #13
0
Datei: net.c Projekt: deurk/qwfwd
int NET_GetPacket(int s, sizebuf_t *msg)
{
	int ret;
	socklen_t fromlen = sizeof (net_from);

	SZ_Clear(msg);

	net_from_socket = s;

	ret = recvfrom(s, (char *)msg->data, msg->maxsize, 0, (struct sockaddr *) &net_from, &fromlen);

	if (ret == SOCKET_ERROR)
	{
		if (qerrno == EWOULDBLOCK)
			return false;

		if (qerrno == EMSGSIZE)
		{
			Sys_Printf ("NET_GetPacket: Oversize packet from %s\n", inet_ntoa(net_from.sin_addr));
			return false;
		}

		if (qerrno == ECONNRESET)
		{
			Sys_DPrintf ("NET_GetPacket: Connection was forcibly closed by %s\n", inet_ntoa(net_from.sin_addr));
			return false;
		}

		Sys_Error ("NET_GetPacket: recvfrom: (%i): %s", qerrno, strerror (qerrno));
	}

	if (ret >= msg->maxsize)
	{
		Sys_Printf ("NET_GetPacket: Oversize packet from %s\n", inet_ntoa(net_from.sin_addr));
		return false;
	}

	msg->cursize = ret;
	msg->data[ret] = 0;

	return ret;
}
Beispiel #14
0
qbool Net_StringToAddr(struct sockaddr_in *address, const char *host, int defaultport)
{
	struct hostent *phe;
	struct sockaddr_in sin = {0};
	char	*colon;
	char	copy[128]; // copy host name without port here.

	memset (address, 0, sizeof(*address));

	sin.sin_family = AF_INET;
	sin.sin_port = htons(defaultport);

	strlcpy (copy, host, sizeof(copy));
	// strip off a trailing :port if present
	for (colon = copy ; *colon ; colon++)
	{
		if (*colon == ':')
		{
			*colon = 0;
			sin.sin_port = htons((short)atoi(colon+1));
		}
	}

	/* Map host name to IP address, allowing for dotted decimal */
	if((phe = gethostbyname(copy)))
	{
		memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
	}
	else if((sin.sin_addr.s_addr = inet_addr(copy)) == INADDR_NONE)
	{
		Sys_DPrintf("Net_StringToAddr: wrong host: %s\n", copy);
		return false;
	}

	*address = sin;
	return true;
}
Beispiel #15
0
static void FWD_check_timeout(void)
{
	byte msg_data[6];
	sizebuf_t msg;
	time_t cur_time;
	double d_cur_time;
	peer_t *p;

	SZ_InitEx(&msg, msg_data, sizeof(msg_data), true);

	cur_time = time(NULL);
	d_cur_time = Sys_DoubleTime();

	for (p = peers; p; p = p->next)
	{
		// this is helper for q3 to guess disconnect asap
		if (p->proto == pr_q3)
		{
			if (cur_time - p->last > 1 && d_cur_time - p->q3_disconnect_check > 0.05 && p->ps == ps_connected)
			{
				p->q3_disconnect_check = d_cur_time;
				SZ_Clear(&msg);
				MSG_WriteLong(&msg, 0);
				MSG_WriteShort(&msg, p->qport);
				NET_SendPacket(p->s, msg.cursize, msg.data, &p->to);
			}
		}

		if (cur_time - p->last < 15) // few seconds timeout
			continue;

		Sys_DPrintf("peer %s:%d timed out\n", inet_ntoa(p->from.sin_addr), (int)ntohs(p->from.sin_port));

		p->ps = ps_drop;
	}
}
Beispiel #16
0
Datei: clc.c Projekt: deurk/qwfwd
// Responses to broadcasts, etc
static qbool CL_ConnectionlessPacket_QW (peer_t *p) 
{
	qbool need_forward = false;
	int c;
	
    MSG_BeginReading();
    MSG_ReadLong();	// Skip the -1

	c = MSG_ReadByte();

	if (MSG_BadRead())
		return need_forward;	// Runt packet

	switch(c) 
	{
		case S2C_CHALLENGE:
		{
			Sys_DPrintf("%s: challenge\n", inet_ntoa(net_from.sin_addr));
			p->challenge = atoi(MSG_ReadString());

			CL_SendConnectPacket_QW(p);

			break;
		}
		case S2C_CONNECTION:
		{
			Sys_DPrintf("%s: connection\n", inet_ntoa(net_from.sin_addr));

			if (p->ps >= ps_connected) 
			{
				Sys_DPrintf("Dup connect received. Ignored.\n");
				break;
			}

			p->ps = ps_connected;

			break;
		}
		case A2C_CLIENT_COMMAND: 
		{
			// Remote command from gui front end
			Sys_DPrintf("%s: client command\n", inet_ntoa(net_from.sin_addr));

			break;
		}
		case A2C_PRINT:		
		{
			// Print command from somewhere.
			
			#ifdef FTE_PEXT_CHUNKEDDOWNLOADS
			if (net_message.cursize > 100 && !strncmp((char *)net_message.data + 5, "\\chunk", sizeof("\\chunk")-1)) 
			{
				CL_Parse_OOB_ChunkedDownload();
				return;
			}
			#endif // FTE_PEXT_CHUNKEDDOWNLOADS

//			Sys_Printf("%s: print\n", inet_ntoa(net_from.sin_addr));
//			Sys_Printf("%s", MSG_ReadString());

			need_forward = true; // so client have chance to see what server trying to say

			break;
		}
		case svc_disconnect:
		{
			Sys_DPrintf("%s: svc_disconnect\n", inet_ntoa(net_from.sin_addr));
			break;
		}
		default:
		{
			Sys_DPrintf("CL CL_ConnectionlessPacket %s:\n%c%s\n", inet_ntoa(net_from.sin_addr), c, MSG_ReadString());
			break;
		}
	}

	return need_forward;
}
Beispiel #17
0
Datei: clc.c Projekt: deurk/qwfwd
static qbool CL_ConnectionlessPacket_Q3 (peer_t *p) 
{
	char	*s, buf[] = "xxx.xxx.xxx.xxx:xxxxx";
	char	*c;
	qbool need_forward = false;
	
    MSG_BeginReading();
    MSG_ReadLong();	// Skip the -1

	s = MSG_ReadStringLine();
	Cmd_TokenizeString( s );
	c = Cmd_Argv(0);

	if ( developer->integer )
	{
		Sys_DPrintf ("CL packet %s: %s\n", NET_AdrToString(&net_from, buf, sizeof(buf)), s);
	}

	// challenge from the server we are connecting to
	if ( !stricmp(c, "challengeResponse") )
	{
		if ( p->ps != ps_challenge )
		{
			Sys_DPrintf( "Unwanted challenge response received.  Ignored.\n" );
		}
		else
		{
			// start sending connect requests instead of challenge request packets
			p->challenge = atoi(Cmd_Argv(1));

			// take this address as the new server address.  This allows
			// a server proxy to hand off connections to multiple servers
//			clc.serverAddress = from;

			Sys_DPrintf ("challengeResponse: %d\n", p->challenge);

			CL_SendConnectPacket_Q3( p );
		}

		return need_forward;
	}

	// server connection
	if ( !stricmp(c, "connectResponse") )
	{
		if ( p->ps >= ps_connected )
		{
			Sys_DPrintf ("Dup connect received.  Ignored.\n");
			return need_forward;
		}

		if ( p->ps != ps_challenge )
		{
			Sys_DPrintf ("connectResponse packet while not connecting.  Ignored.\n");
			return need_forward;
		}

		Sys_DPrintf ("connectResponse\n");

		// we are connected now
		p->ps = ps_connected;

// possibile to lost this message, so moved to the other place where it sended time to time
//		Netchan_OutOfBandPrint(net_socket, &p->from, "print\n" "/reconnect ASAP!\n");

		return need_forward;
	}

	// a disconnect message from the server, which will happen if the server
	// dropped the connection but it is still getting packets from us
	if ( !stricmp(c, "disconnect") )
	{
//		CL_DisconnectPacket( from );
		p->ps = ps_drop; // drop this peer
		return need_forward = true; // so client have chance to see what server trying to say
	}

	// echo request from server
	if ( !stricmp(c, "print") )
	{
		Sys_DPrintf( "%s", MSG_ReadString() );
		return need_forward = true; // so client have chance to see what server trying to say
	}

	return need_forward;
}