2001-02-19 21:15:25 +00:00
|
|
|
/*
|
|
|
|
net_dgrm.c
|
|
|
|
|
2011-07-26 05:15:41 +00:00
|
|
|
Datagram network driver.
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
2003-01-15 15:31:36 +00:00
|
|
|
|
2001-05-09 05:41:34 +00:00
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-03-27 20:33:07 +00:00
|
|
|
#include "QF/cmd.h"
|
2001-05-31 03:41:35 +00:00
|
|
|
#include "QF/cvar.h"
|
2001-03-27 20:33:07 +00:00
|
|
|
#include "QF/sys.h"
|
2022-04-24 15:23:28 +00:00
|
|
|
#include "QF/heapsort.h"
|
2001-03-27 20:33:07 +00:00
|
|
|
#include "QF/keys.h"
|
|
|
|
#include "QF/qendian.h"
|
|
|
|
#include "QF/msg.h"
|
|
|
|
#include "QF/qargs.h"
|
2001-04-15 21:11:41 +00:00
|
|
|
#include "QF/screen.h"
|
|
|
|
|
2003-02-11 22:48:57 +00:00
|
|
|
#include "netmain.h"
|
|
|
|
|
2022-06-03 06:43:53 +00:00
|
|
|
//FIXME these should not be here!!!
|
2022-11-02 06:08:09 +00:00
|
|
|
#include "client/screen.h"
|
2022-06-03 06:43:53 +00:00
|
|
|
#include "../nq/include/client.h"
|
2003-02-11 22:48:57 +00:00
|
|
|
#include "../nq/include/server.h"
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// This is enables a simple IP banning mechanism
|
|
|
|
#define BAN_TEST
|
|
|
|
|
|
|
|
#ifdef BAN_TEST
|
|
|
|
#if defined(_WIN32)
|
2010-12-23 02:40:16 +00:00
|
|
|
#include "winquake.h"
|
|
|
|
typedef uint32_t in_addr_t;
|
2001-02-19 21:15:25 +00:00
|
|
|
#else
|
2009-12-19 10:54:23 +00:00
|
|
|
# include <sys/socket.h>
|
|
|
|
# include <netinet/in.h>
|
|
|
|
# include <arpa/inet.h>
|
2001-02-19 21:15:25 +00:00
|
|
|
#endif
|
2001-02-26 06:48:02 +00:00
|
|
|
#endif // BAN_TEST
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
#include "net_dgrm.h"
|
|
|
|
|
|
|
|
// these two macros are to make the code more readable
|
|
|
|
#define sfunc net_landrivers[sock->landriver]
|
|
|
|
#define dfunc net_landrivers[net_landriverlevel]
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
static int net_landriverlevel;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
/* statistic counters */
|
2001-02-26 06:48:02 +00:00
|
|
|
int packetsSent = 0;
|
|
|
|
int packetsReSent = 0;
|
|
|
|
int packetsReceived = 0;
|
|
|
|
int receivedDuplicateCount = 0;
|
|
|
|
int shortPacketCount = 0;
|
|
|
|
int droppedDatagrams;
|
|
|
|
|
|
|
|
static int myDriverLevel;
|
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
static byte dgrm_send_packet_data[MAX_DATAGRAM + NET_HEADERSIZE];
|
|
|
|
static sizebuf_t dgrm_send_packet = {
|
|
|
|
.data = dgrm_send_packet_data,
|
|
|
|
.maxsize = sizeof (dgrm_send_packet_data),
|
|
|
|
};
|
|
|
|
|
|
|
|
static byte dgrm_receive_packet_data[MAX_DATAGRAM + NET_HEADERSIZE];
|
|
|
|
static sizebuf_t dgrm_receive_packet = {
|
|
|
|
.data = dgrm_receive_packet_data,
|
|
|
|
.maxsize = sizeof (dgrm_receive_packet_data),
|
|
|
|
};
|
|
|
|
static qmsg_t dgrm_message = {
|
|
|
|
.message = &dgrm_receive_packet,
|
|
|
|
};
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-03-04 07:43:27 +00:00
|
|
|
// FIXME: MENUCODE
|
|
|
|
//extern int m_return_state;
|
|
|
|
//extern int m_state;
|
2023-06-13 09:06:11 +00:00
|
|
|
//extern bool m_return_onerror;
|
2001-03-04 07:43:27 +00:00
|
|
|
//extern char m_return_reason[32];
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef BAN_TEST
|
2009-12-19 10:54:23 +00:00
|
|
|
in_addr_t banAddr = 0x00000000;
|
|
|
|
in_addr_t banMask = 0xffffffff;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2001-02-26 06:48:02 +00:00
|
|
|
NET_Ban_f (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2003-07-08 20:11:10 +00:00
|
|
|
char addrStr[32]; //FIXME: overflow
|
|
|
|
char maskStr[32]; //FIXME: overflow
|
2021-03-27 10:52:59 +00:00
|
|
|
__attribute__((format(PRINTF, 1, 2))) void (*print) (const char *fmt, ...);
|
2001-02-26 06:48:02 +00:00
|
|
|
|
|
|
|
if (cmd_source == src_command) {
|
|
|
|
if (!sv.active) {
|
2002-07-31 05:19:03 +00:00
|
|
|
CL_Cmd_ForwardToServer ();
|
2001-02-19 21:15:25 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-11-06 10:17:14 +00:00
|
|
|
print = Sys_Printf;
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
2021-04-04 03:20:01 +00:00
|
|
|
if (*sv_globals.deathmatch && !host_client->privileged) {
|
|
|
|
return;
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
print = SV_ClientPrintf;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
switch (Cmd_Argc ()) {
|
2001-02-19 21:15:25 +00:00
|
|
|
case 1:
|
2021-04-04 03:20:01 +00:00
|
|
|
if (banAddr) {
|
|
|
|
struct in_addr t;
|
|
|
|
t.s_addr = banAddr;
|
|
|
|
strcpy (addrStr, inet_ntoa (t));
|
|
|
|
t.s_addr = banMask;
|
|
|
|
strcpy (maskStr, inet_ntoa (t));
|
|
|
|
print ("Banning %s [%s]\n", addrStr, maskStr);
|
|
|
|
} else {
|
|
|
|
print ("Banning not active\n");
|
|
|
|
}
|
|
|
|
break;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
case 2:
|
2021-04-04 03:20:01 +00:00
|
|
|
if (strcasecmp (Cmd_Argv (1), "off") == 0) {
|
|
|
|
banAddr = 0x00000000;
|
|
|
|
} else {
|
|
|
|
banAddr = inet_addr (Cmd_Argv (1));
|
|
|
|
}
|
|
|
|
banMask = 0xffffffff;
|
|
|
|
break;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
case 3:
|
2021-04-04 03:20:01 +00:00
|
|
|
banAddr = inet_addr (Cmd_Argv (1));
|
|
|
|
banMask = inet_addr (Cmd_Argv (2));
|
|
|
|
break;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
default:
|
2021-04-04 03:20:01 +00:00
|
|
|
print ("BAN ip_address [mask]\n");
|
|
|
|
break;
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
int
|
2011-08-02 06:22:33 +00:00
|
|
|
Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2021-04-04 03:20:01 +00:00
|
|
|
unsigned packetLen;
|
|
|
|
unsigned dataLen;
|
|
|
|
unsigned eom;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
memcpy (sock->sendMessage, data->data, data->cursize);
|
2001-02-19 21:15:25 +00:00
|
|
|
sock->sendMessageLength = data->cursize;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (data->cursize <= MAX_DATAGRAM) {
|
2001-02-19 21:15:25 +00:00
|
|
|
dataLen = data->cursize;
|
|
|
|
eom = NETFLAG_EOM;
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
2001-02-19 21:15:25 +00:00
|
|
|
dataLen = MAX_DATAGRAM;
|
|
|
|
eom = 0;
|
|
|
|
}
|
|
|
|
packetLen = NET_HEADERSIZE + dataLen;
|
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
SZ_Clear (&dgrm_send_packet);
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, packetLen | (NETFLAG_DATA | eom));
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, sock->sendSequence++);
|
|
|
|
MSG_WriteBytes (&dgrm_send_packet, sock->sendMessage, dataLen);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
sock->canSend = false;
|
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
if (sfunc.Write (sock->socket, dgrm_send_packet.data,
|
|
|
|
dgrm_send_packet.cursize, &sock->addr) == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return -1;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
sock->lastSendTime = net_time;
|
|
|
|
packetsSent++;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static int
|
2011-08-02 06:22:33 +00:00
|
|
|
SendMessageNext (qsocket_t *sock)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2021-04-04 03:20:01 +00:00
|
|
|
unsigned packetLen;
|
|
|
|
unsigned dataLen;
|
|
|
|
unsigned eom;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (sock->sendMessageLength <= MAX_DATAGRAM) {
|
2001-02-19 21:15:25 +00:00
|
|
|
dataLen = sock->sendMessageLength;
|
|
|
|
eom = NETFLAG_EOM;
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
2001-02-19 21:15:25 +00:00
|
|
|
dataLen = MAX_DATAGRAM;
|
|
|
|
eom = 0;
|
|
|
|
}
|
|
|
|
packetLen = NET_HEADERSIZE + dataLen;
|
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
SZ_Clear (&dgrm_send_packet);
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, packetLen | (NETFLAG_DATA | eom));
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, sock->sendSequence++);
|
|
|
|
MSG_WriteBytes (&dgrm_send_packet, sock->sendMessage, dataLen);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
sock->sendNext = false;
|
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
if (sfunc.Write (sock->socket, dgrm_send_packet.data,
|
|
|
|
dgrm_send_packet.cursize, &sock->addr) == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return -1;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
sock->lastSendTime = net_time;
|
|
|
|
packetsSent++;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static int
|
2011-08-02 06:22:33 +00:00
|
|
|
ReSendMessage (qsocket_t *sock)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2021-04-04 03:20:01 +00:00
|
|
|
unsigned packetLen;
|
|
|
|
unsigned dataLen;
|
|
|
|
unsigned eom;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (sock->sendMessageLength <= MAX_DATAGRAM) {
|
2001-02-19 21:15:25 +00:00
|
|
|
dataLen = sock->sendMessageLength;
|
|
|
|
eom = NETFLAG_EOM;
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
2001-02-19 21:15:25 +00:00
|
|
|
dataLen = MAX_DATAGRAM;
|
|
|
|
eom = 0;
|
|
|
|
}
|
|
|
|
packetLen = NET_HEADERSIZE + dataLen;
|
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
SZ_Clear (&dgrm_send_packet);
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, packetLen | (NETFLAG_DATA | eom));
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, sock->sendSequence - 1);
|
|
|
|
MSG_WriteBytes (&dgrm_send_packet, sock->sendMessage, dataLen);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
sock->sendNext = false;
|
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
if (sfunc.Write (sock->socket, dgrm_send_packet.data,
|
|
|
|
dgrm_send_packet.cursize, &sock->addr) == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return -1;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
sock->lastSendTime = net_time;
|
|
|
|
packetsReSent++;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-06-13 09:06:11 +00:00
|
|
|
bool
|
2011-08-02 06:22:33 +00:00
|
|
|
Datagram_CanSendMessage (qsocket_t *sock)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2021-04-04 03:20:01 +00:00
|
|
|
if (sock->sendNext) {
|
2001-02-19 21:15:25 +00:00
|
|
|
SendMessageNext (sock);
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
return sock->canSend;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-06-13 09:06:11 +00:00
|
|
|
__attribute__((const)) bool
|
2011-08-02 06:22:33 +00:00
|
|
|
Datagram_CanSendUnreliableMessage (qsocket_t *sock)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
int
|
2011-08-02 06:22:33 +00:00
|
|
|
Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int packetLen;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
packetLen = NET_HEADERSIZE + data->cursize;
|
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
SZ_Clear (&dgrm_send_packet);
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, packetLen | NETFLAG_UNRELIABLE);
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, sock->unreliableSendSequence++);
|
|
|
|
MSG_WriteBytes (&dgrm_send_packet, data->data, data->cursize);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
if (sfunc.Write (sock->socket, dgrm_send_packet.data,
|
|
|
|
dgrm_send_packet.cursize, &sock->addr) == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return -1;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
packetsSent++;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
int
|
2011-08-02 06:22:33 +00:00
|
|
|
Datagram_GetMessage (qsocket_t *sock)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2021-04-04 03:20:01 +00:00
|
|
|
unsigned length;
|
|
|
|
unsigned flags;
|
2001-02-26 06:48:02 +00:00
|
|
|
int ret = 0;
|
2011-09-04 00:00:42 +00:00
|
|
|
netadr_t readaddr;
|
2021-04-04 03:20:01 +00:00
|
|
|
unsigned sequence;
|
|
|
|
unsigned count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2011-08-02 06:22:33 +00:00
|
|
|
/// If there is an outstanding reliable packet and more than 1 second has
|
|
|
|
/// passed, resend the packet.
|
2021-04-04 03:20:01 +00:00
|
|
|
if (!sock->canSend) {
|
|
|
|
if ((net_time - sock->lastSendTime) > 1.0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
ReSendMessage (sock);
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
while (1) {
|
2021-04-04 08:01:53 +00:00
|
|
|
SZ_Clear (&dgrm_receive_packet);
|
|
|
|
length = sfunc.Read (sock->socket, dgrm_receive_packet.data,
|
|
|
|
dgrm_receive_packet.maxsize, &readaddr);
|
|
|
|
dgrm_receive_packet.cursize = length;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
// if ((rand() & 255) > 220)
|
|
|
|
// continue;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
if (length == 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
break;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2003-04-17 00:01:48 +00:00
|
|
|
if ((int) length == -1) {
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("Read error\n");
|
2001-02-19 21:15:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (sfunc.AddrCompare (&readaddr, &sock->addr) != 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (length < NET_HEADERSIZE) {
|
2001-02-19 21:15:25 +00:00
|
|
|
shortPacketCount++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_BeginReading (&dgrm_message);
|
|
|
|
length = MSG_ReadLongBE (&dgrm_message);
|
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
flags = length & (~NETFLAG_LENGTH_MASK);
|
|
|
|
length &= NETFLAG_LENGTH_MASK;
|
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
if (flags & NETFLAG_CTL) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
sequence = MSG_ReadLongBE (&dgrm_message);
|
2001-02-19 21:15:25 +00:00
|
|
|
packetsReceived++;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (flags & NETFLAG_UNRELIABLE) {
|
|
|
|
if (sequence < sock->unreliableReceiveSequence) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "Got a stale datagram\n");
|
2001-02-19 21:15:25 +00:00
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
if (sequence != sock->unreliableReceiveSequence) {
|
2001-02-19 21:15:25 +00:00
|
|
|
count = sequence - sock->unreliableReceiveSequence;
|
|
|
|
droppedDatagrams += count;
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "Dropped %u datagram(s)\n", count);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
sock->unreliableReceiveSequence = sequence + 1;
|
|
|
|
|
|
|
|
length -= NET_HEADERSIZE;
|
|
|
|
|
2011-08-02 06:22:33 +00:00
|
|
|
/// Copy unreliable data to net_message
|
2001-02-23 23:16:13 +00:00
|
|
|
SZ_Clear (net_message->message);
|
2021-04-04 08:01:53 +00:00
|
|
|
byte *buf = SZ_GetSpace (net_message->message, length);
|
|
|
|
MSG_ReadBytes (&dgrm_message, buf, length);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
ret = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (flags & NETFLAG_ACK) {
|
|
|
|
if (sequence != (sock->sendSequence - 1)) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "Stale ACK received\n");
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
if (sequence == sock->ackSequence) {
|
2001-02-19 21:15:25 +00:00
|
|
|
sock->ackSequence++;
|
2021-04-04 03:20:01 +00:00
|
|
|
if (sock->ackSequence != sock->sendSequence) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "ack sequencing error\n");
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "Duplicate ACK received\n");
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
sock->sendMessageLength -= MAX_DATAGRAM;
|
2001-02-26 06:48:02 +00:00
|
|
|
if (sock->sendMessageLength > 0) {
|
|
|
|
memcpy (sock->sendMessage, sock->sendMessage + MAX_DATAGRAM,
|
|
|
|
sock->sendMessageLength);
|
2001-02-19 21:15:25 +00:00
|
|
|
sock->sendNext = true;
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
2001-02-19 21:15:25 +00:00
|
|
|
sock->sendMessageLength = 0;
|
|
|
|
sock->canSend = true;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (flags & NETFLAG_DATA) {
|
2021-04-04 08:01:53 +00:00
|
|
|
SZ_Clear (&dgrm_send_packet);
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, NET_HEADERSIZE | NETFLAG_ACK);
|
|
|
|
MSG_WriteLongBE (&dgrm_send_packet, sequence);
|
|
|
|
sfunc.Write (sock->socket, dgrm_send_packet.data,
|
|
|
|
dgrm_send_packet.cursize, &readaddr);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (sequence != sock->receiveSequence) {
|
2001-02-19 21:15:25 +00:00
|
|
|
receivedDuplicateCount++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
sock->receiveSequence++;
|
|
|
|
|
|
|
|
length -= NET_HEADERSIZE;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (flags & NETFLAG_EOM) {
|
|
|
|
SZ_Clear (net_message->message);
|
|
|
|
SZ_Write (net_message->message, sock->receiveMessage,
|
|
|
|
sock->receiveMessageLength);
|
2021-04-04 08:01:53 +00:00
|
|
|
byte *buf = SZ_GetSpace (net_message->message, length);
|
|
|
|
MSG_ReadBytes (&dgrm_message, buf, length);
|
2001-02-19 21:15:25 +00:00
|
|
|
sock->receiveMessageLength = 0;
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-08-02 06:22:33 +00:00
|
|
|
/// Append reliable data to sock->receiveMessage.
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_ReadBytes (&dgrm_message,
|
|
|
|
sock->receiveMessage + sock->receiveMessageLength,
|
|
|
|
length);
|
2001-02-19 21:15:25 +00:00
|
|
|
sock->receiveMessageLength += length;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
if (sock->sendNext) {
|
2001-02-19 21:15:25 +00:00
|
|
|
SendMessageNext (sock);
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2011-08-02 06:22:33 +00:00
|
|
|
PrintStats (qsocket_t *s)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("canSend = %4u \n", s->canSend);
|
|
|
|
Sys_Printf ("sendSeq = %4u ", s->sendSequence);
|
|
|
|
Sys_Printf ("recvSeq = %4u \n", s->receiveSequence);
|
|
|
|
Sys_Printf ("\n");
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2001-02-26 06:48:02 +00:00
|
|
|
NET_Stats_f (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
qsocket_t *s;
|
|
|
|
|
|
|
|
if (Cmd_Argc () == 1) {
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("unreliable messages sent = %i\n",
|
2001-02-26 06:48:02 +00:00
|
|
|
unreliableMessagesSent);
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("unreliable messages recv = %i\n",
|
2001-02-26 06:48:02 +00:00
|
|
|
unreliableMessagesReceived);
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("reliable messages sent = %i\n", messagesSent);
|
|
|
|
Sys_Printf ("reliable messages received = %i\n", messagesReceived);
|
|
|
|
Sys_Printf ("packetsSent = %i\n", packetsSent);
|
|
|
|
Sys_Printf ("packetsReSent = %i\n", packetsReSent);
|
|
|
|
Sys_Printf ("packetsReceived = %i\n", packetsReceived);
|
|
|
|
Sys_Printf ("receivedDuplicateCount = %i\n",
|
2001-02-26 06:48:02 +00:00
|
|
|
receivedDuplicateCount);
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("shortPacketCount = %i\n", shortPacketCount);
|
|
|
|
Sys_Printf ("droppedDatagrams = %i\n", droppedDatagrams);
|
2001-02-26 06:48:02 +00:00
|
|
|
} else if (strcmp (Cmd_Argv (1), "*") == 0) {
|
2021-04-04 03:20:01 +00:00
|
|
|
for (s = net_activeSockets; s; s = s->next) {
|
2001-02-26 06:48:02 +00:00
|
|
|
PrintStats (s);
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
for (s = net_freeSockets; s; s = s->next) {
|
2001-02-26 06:48:02 +00:00
|
|
|
PrintStats (s);
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
2021-04-04 03:20:01 +00:00
|
|
|
for (s = net_activeSockets; s; s = s->next) {
|
|
|
|
if (strcasecmp (Cmd_Argv (1), s->address) == 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
break;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (s == NULL) {
|
|
|
|
for (s = net_freeSockets; s; s = s->next) {
|
|
|
|
if (strcasecmp (Cmd_Argv (1), s->address) == 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
break;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (s == NULL) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
PrintStats (s);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
int
|
|
|
|
Datagram_Init (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int i;
|
|
|
|
int csock;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
myDriverLevel = net_driverlevel;
|
2001-02-21 19:35:06 +00:00
|
|
|
Cmd_AddCommand ("net_stats", NET_Stats_f, "No Description");
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
if (COM_CheckParm ("-nolan")) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return -1;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
for (i = 0; i < net_numlandrivers; i++) {
|
2001-02-19 21:15:25 +00:00
|
|
|
csock = net_landrivers[i].Init ();
|
2021-04-04 03:20:01 +00:00
|
|
|
if (csock == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
net_landrivers[i].initialized = true;
|
|
|
|
net_landrivers[i].controlSock = csock;
|
2001-02-26 06:48:02 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
#ifdef BAN_TEST
|
2001-02-21 19:35:06 +00:00
|
|
|
Cmd_AddCommand ("ban", NET_Ban_f, "No Description");
|
2001-02-19 21:15:25 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
|
|
|
Datagram_Shutdown (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int i;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// shutdown the lan drivers
|
|
|
|
//
|
2001-02-26 06:48:02 +00:00
|
|
|
for (i = 0; i < net_numlandrivers; i++) {
|
|
|
|
if (net_landrivers[i].initialized) {
|
2001-02-19 21:15:25 +00:00
|
|
|
net_landrivers[i].Shutdown ();
|
|
|
|
net_landrivers[i].initialized = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
2011-08-02 06:22:33 +00:00
|
|
|
Datagram_Close (qsocket_t *sock)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
sfunc.CloseSocket (sock->socket);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
2023-06-13 09:06:11 +00:00
|
|
|
Datagram_Listen (bool state)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int i;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
for (i = 0; i < net_numlandrivers; i++) {
|
|
|
|
if (net_landrivers[i].initialized) {
|
2001-02-19 21:15:25 +00:00
|
|
|
net_landrivers[i].Listen (state);
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2022-04-24 15:23:28 +00:00
|
|
|
static const cvar_t **cvar_list;
|
|
|
|
static int num_cvars;
|
|
|
|
|
|
|
|
static int
|
|
|
|
dg_cvar_cmp (const void *_a, const void *_b)
|
|
|
|
{
|
|
|
|
const cvar_t * const *a = _a;
|
|
|
|
const cvar_t * const *b = _b;
|
|
|
|
return strcmp ((*a)->name, (*b)->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
dg_cvar_select (const cvar_t *cvar, void *data)
|
|
|
|
{
|
|
|
|
if (cvar->flags & CVAR_SERVERINFO) {
|
|
|
|
*(int *)data += 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
static qsocket_t *
|
|
|
|
_Datagram_CheckNewConnections (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2011-09-04 00:00:42 +00:00
|
|
|
netadr_t clientaddr;
|
|
|
|
netadr_t newaddr;
|
2001-02-26 06:48:02 +00:00
|
|
|
int newsock;
|
|
|
|
int acceptsock;
|
|
|
|
qsocket_t *sock;
|
|
|
|
qsocket_t *s;
|
|
|
|
int len;
|
|
|
|
int command;
|
|
|
|
int control;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
acceptsock = dfunc.CheckNewConnections ();
|
2021-04-04 03:20:01 +00:00
|
|
|
if (acceptsock == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
len = dfunc.Read (acceptsock, net_message->message->data,
|
|
|
|
net_message->message->maxsize, &clientaddr);
|
|
|
|
if (len < (int) sizeof (int)) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-02-23 23:16:13 +00:00
|
|
|
net_message->message->cursize = len;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-23 23:16:13 +00:00
|
|
|
MSG_BeginReading (net_message);
|
2021-04-04 08:01:53 +00:00
|
|
|
control = MSG_ReadLongBE (net_message);
|
2021-04-04 03:20:01 +00:00
|
|
|
if (control == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
if ((control & NETFLAG_LENGTH_MASK) != len) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
command = MSG_ReadByte (net_message);
|
|
|
|
if (command == CCREQ_SERVER_INFO) {
|
2021-04-04 03:20:01 +00:00
|
|
|
if (strcmp (MSG_ReadString (net_message), "QUAKE") != 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREP_SERVER_INFO);
|
|
|
|
dfunc.GetSocketAddr (acceptsock, &newaddr);
|
|
|
|
MSG_WriteString (net_message->message, dfunc.AddrToString (&newaddr));
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
MSG_WriteString (net_message->message, hostname);
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteString (net_message->message, sv.name);
|
|
|
|
MSG_WriteByte (net_message->message, net_activeconnections);
|
|
|
|
MSG_WriteByte (net_message->message, svs.maxclients);
|
|
|
|
MSG_WriteByte (net_message->message, NET_PROTOCOL_VERSION);
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Write (acceptsock, net_message->message->data,
|
|
|
|
net_message->message->cursize, &clientaddr);
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (command == CCREQ_PLAYER_INFO) {
|
|
|
|
int playerNumber;
|
|
|
|
int activeNumber;
|
2022-01-16 13:15:18 +00:00
|
|
|
unsigned clientNumber;
|
2001-02-26 06:48:02 +00:00
|
|
|
client_t *client;
|
|
|
|
|
|
|
|
playerNumber = MSG_ReadByte (net_message);
|
2001-02-19 21:15:25 +00:00
|
|
|
activeNumber = -1;
|
2001-02-26 06:48:02 +00:00
|
|
|
for (clientNumber = 0, client = svs.clients;
|
|
|
|
clientNumber < svs.maxclients; clientNumber++, client++) {
|
|
|
|
if (client->active) {
|
2001-02-19 21:15:25 +00:00
|
|
|
activeNumber++;
|
2021-04-04 03:20:01 +00:00
|
|
|
if (activeNumber == playerNumber) {
|
2001-02-19 21:15:25 +00:00
|
|
|
break;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
2021-04-04 03:20:01 +00:00
|
|
|
if (clientNumber == svs.maxclients) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREP_PLAYER_INFO);
|
|
|
|
MSG_WriteByte (net_message->message, playerNumber);
|
|
|
|
MSG_WriteString (net_message->message, client->name);
|
|
|
|
MSG_WriteLong (net_message->message, client->colors);
|
2001-08-08 20:28:53 +00:00
|
|
|
MSG_WriteLong (net_message->message, SVfloat (client->edict, frags));
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message,
|
|
|
|
(int) (net_time - client->netconnection->connecttime));
|
|
|
|
MSG_WriteString (net_message->message, client->netconnection->address);
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Write (acceptsock, net_message->message->data,
|
|
|
|
net_message->message->cursize, &clientaddr);
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (command == CCREQ_RULE_INFO) {
|
2001-10-18 04:44:58 +00:00
|
|
|
const char *prevCvarName;
|
2022-04-24 15:23:28 +00:00
|
|
|
const cvar_t *var;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// find the search start location
|
2001-02-26 06:48:02 +00:00
|
|
|
prevCvarName = MSG_ReadString (net_message);
|
|
|
|
if (*prevCvarName) {
|
2022-04-24 15:23:28 +00:00
|
|
|
cvar_t key = { .name = prevCvarName };
|
|
|
|
var = bsearch (&key, cvar_list, num_cvars, sizeof (cvar_t *),
|
|
|
|
dg_cvar_cmp);
|
2001-02-19 21:15:25 +00:00
|
|
|
if (!var)
|
2022-04-24 15:23:28 +00:00
|
|
|
return 0;
|
|
|
|
var++;
|
2021-04-04 03:20:01 +00:00
|
|
|
} else {
|
2022-04-24 15:23:28 +00:00
|
|
|
if (cvar_list) {
|
|
|
|
free (cvar_list);
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2022-04-24 15:23:28 +00:00
|
|
|
num_cvars = 0;
|
|
|
|
cvar_list = Cvar_Select (dg_cvar_select, &num_cvars);
|
|
|
|
heapsort (cvar_list, num_cvars, sizeof (cvar_t *), dg_cvar_cmp);
|
|
|
|
var = cvar_list[0];
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// send the response
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREP_RULE_INFO);
|
|
|
|
if (var) {
|
|
|
|
MSG_WriteString (net_message->message, var->name);
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
MSG_WriteString (net_message->message, Cvar_VarString (var));
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Write (acceptsock, net_message->message->data,
|
|
|
|
net_message->message->cursize, &clientaddr);
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
if (command != CCREQ_CONNECT) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
if (strcmp (MSG_ReadString (net_message), "QUAKE") != 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (MSG_ReadByte (net_message) != NET_PROTOCOL_VERSION) {
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREP_REJECT);
|
|
|
|
MSG_WriteString (net_message->message, "Incompatible version.\n");
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Write (acceptsock, net_message->message->data,
|
|
|
|
net_message->message->cursize, &clientaddr);
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#ifdef BAN_TEST
|
|
|
|
// check for a ban
|
2011-09-04 00:00:42 +00:00
|
|
|
if (clientaddr.family == AF_INET) {
|
2005-10-23 13:19:21 +00:00
|
|
|
unsigned testAddr;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2011-09-04 00:00:42 +00:00
|
|
|
memcpy (&testAddr, clientaddr.ip, 4);
|
2001-02-26 06:48:02 +00:00
|
|
|
if ((testAddr & banMask) == banAddr) {
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREP_REJECT);
|
|
|
|
MSG_WriteString (net_message->message, "You have been banned.\n");
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Write (acceptsock, net_message->message->data,
|
|
|
|
net_message->message->cursize, &clientaddr);
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// see if this guy is already connected
|
2001-02-26 06:48:02 +00:00
|
|
|
for (s = net_activeSockets; s; s = s->next) {
|
2021-04-04 03:20:01 +00:00
|
|
|
if (s->driver != net_driverlevel) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
ret = dfunc.AddrCompare (&clientaddr, &s->addr);
|
|
|
|
if (ret >= 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
// is this a duplicate connection reqeust?
|
2001-02-26 06:48:02 +00:00
|
|
|
if (ret == 0 && net_time - s->connecttime < 2.0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
// yes, so send a duplicate reply
|
2001-02-26 06:48:02 +00:00
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREP_ACCEPT);
|
|
|
|
dfunc.GetSocketAddr (s->socket, &newaddr);
|
|
|
|
MSG_WriteLong (net_message->message,
|
|
|
|
dfunc.GetSocketPort (&newaddr));
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Write (acceptsock, net_message->message->data,
|
|
|
|
net_message->message->cursize, &clientaddr);
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
// it's somebody coming back in from a crash/disconnect
|
|
|
|
// so close the old qsocket and let their retry get them back in
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "closing stale socket %d %g\n", ret,
|
2011-08-02 08:36:38 +00:00
|
|
|
net_time - s->connecttime);
|
2001-02-26 06:48:02 +00:00
|
|
|
NET_Close (s);
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// allocate a QSocket
|
|
|
|
sock = NET_NewQSocket ();
|
2001-02-26 06:48:02 +00:00
|
|
|
if (sock == NULL) {
|
2001-02-19 21:15:25 +00:00
|
|
|
// no room; try to let him know
|
2001-02-26 06:48:02 +00:00
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREP_REJECT);
|
|
|
|
MSG_WriteString (net_message->message, "Server is full.\n");
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Write (acceptsock, net_message->message->data,
|
|
|
|
net_message->message->cursize, &clientaddr);
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
// allocate a network socket
|
2001-02-26 06:48:02 +00:00
|
|
|
newsock = dfunc.OpenSocket (0);
|
|
|
|
if (newsock == -1) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "failed to open socket");
|
2001-02-26 06:48:02 +00:00
|
|
|
NET_FreeQSocket (sock);
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
// connect to the client
|
2001-02-26 06:48:02 +00:00
|
|
|
if (dfunc.Connect (newsock, &clientaddr) == -1) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "failed to connect client");
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.CloseSocket (newsock);
|
|
|
|
NET_FreeQSocket (sock);
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-05-21 23:23:22 +00:00
|
|
|
// everything is allocated, just fill in the details
|
2001-02-19 21:15:25 +00:00
|
|
|
sock->socket = newsock;
|
|
|
|
sock->landriver = net_landriverlevel;
|
|
|
|
sock->addr = clientaddr;
|
2001-02-26 06:48:02 +00:00
|
|
|
strcpy (sock->address, dfunc.AddrToString (&clientaddr));
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
// send him back the info about the server connection he has been
|
|
|
|
// allocated
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREP_ACCEPT);
|
|
|
|
dfunc.GetSocketAddr (newsock, &newaddr);
|
|
|
|
MSG_WriteLong (net_message->message, dfunc.GetSocketPort (&newaddr));
|
|
|
|
// MSG_WriteString(net_message->message, dfunc.AddrToString(&newaddr));
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Write (acceptsock, net_message->message->data,
|
|
|
|
net_message->message->cursize, &clientaddr);
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
return sock;
|
|
|
|
}
|
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
qsocket_t *
|
2001-02-26 06:48:02 +00:00
|
|
|
Datagram_CheckNewConnections (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
qsocket_t *ret = NULL;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers;
|
|
|
|
net_landriverlevel++)
|
2001-02-19 21:15:25 +00:00
|
|
|
if (net_landrivers[net_landriverlevel].initialized)
|
|
|
|
if ((ret = _Datagram_CheckNewConnections ()) != NULL)
|
|
|
|
break;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
static void
|
2023-06-13 09:06:11 +00:00
|
|
|
_Datagram_SearchForHosts (bool xmit)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int ret;
|
2011-09-04 00:00:42 +00:00
|
|
|
netadr_t readaddr;
|
|
|
|
netadr_t myaddr;
|
2001-02-26 06:48:02 +00:00
|
|
|
int control;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
|
2001-02-26 06:48:02 +00:00
|
|
|
if (xmit) {
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREQ_SERVER_INFO);
|
|
|
|
MSG_WriteString (net_message->message, "QUAKE");
|
|
|
|
MSG_WriteByte (net_message->message, NET_PROTOCOL_VERSION);
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Broadcast (dfunc.controlSock, net_message->message->data,
|
|
|
|
net_message->message->cursize);
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
while ((ret = dfunc.Read (dfunc.controlSock, net_message->message->data,
|
|
|
|
net_message->message->maxsize, &readaddr)) > 0) {
|
|
|
|
if (ret < (int) sizeof (int)) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-02-23 23:16:13 +00:00
|
|
|
net_message->message->cursize = ret;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// don't answer our own query
|
2021-04-04 03:20:01 +00:00
|
|
|
if (dfunc.AddrCompare (&readaddr, &myaddr) >= 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-23 23:16:13 +00:00
|
|
|
MSG_BeginReading (net_message);
|
2021-04-04 08:01:53 +00:00
|
|
|
control = MSG_ReadLongBE (net_message);
|
2021-04-04 03:20:01 +00:00
|
|
|
if (control == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
if ((control & NETFLAG_LENGTH_MASK) != ret) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 03:20:01 +00:00
|
|
|
if (MSG_ReadByte (net_message) != CCREP_SERVER_INFO) {
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 09:38:14 +00:00
|
|
|
const char *addrstr = MSG_ReadString (net_message);
|
|
|
|
dfunc.GetAddrFromName (addrstr, &readaddr);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 09:38:14 +00:00
|
|
|
const char *name = MSG_ReadString (net_message);
|
|
|
|
const char *map = MSG_ReadString (net_message);
|
|
|
|
int users = MSG_ReadByte (net_message);
|
|
|
|
int maxusers = MSG_ReadByte (net_message);
|
|
|
|
int protocol = MSG_ReadByte (net_message);
|
|
|
|
const char *cname = dfunc.AddrToString (&readaddr);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 09:38:14 +00:00
|
|
|
if (protocol != NET_PROTOCOL_VERSION) {
|
|
|
|
char *new_name = alloca (strlen (name) + 2);
|
|
|
|
new_name[0] = '*';
|
|
|
|
strcpy (new_name + 1, name);
|
|
|
|
name = new_name;
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2021-04-04 09:38:14 +00:00
|
|
|
NET_AddCachedHost (name, map, cname, users, maxusers, net_driverlevel,
|
|
|
|
net_landriverlevel, &readaddr);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
2023-06-13 09:06:11 +00:00
|
|
|
Datagram_SearchForHosts (bool xmit)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers;
|
|
|
|
net_landriverlevel++) {
|
2021-04-04 03:20:01 +00:00
|
|
|
if (net_landrivers[net_landriverlevel].initialized) {
|
2001-02-19 21:15:25 +00:00
|
|
|
_Datagram_SearchForHosts (xmit);
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
static qsocket_t *
|
2001-07-15 07:04:17 +00:00
|
|
|
_Datagram_Connect (const char *host)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2011-09-04 00:00:42 +00:00
|
|
|
netadr_t sendaddr;
|
|
|
|
netadr_t readaddr;
|
2001-02-26 06:48:02 +00:00
|
|
|
qsocket_t *sock;
|
|
|
|
int newsock;
|
|
|
|
int ret;
|
|
|
|
int reps;
|
|
|
|
double start_time;
|
|
|
|
int control;
|
2001-10-18 04:44:58 +00:00
|
|
|
const char *reason;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// see if we can resolve the host name
|
2021-04-04 03:20:01 +00:00
|
|
|
if (dfunc.GetAddrFromName (host, &sendaddr) == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
newsock = dfunc.OpenSocket (0);
|
2021-04-04 03:20:01 +00:00
|
|
|
if (newsock == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
sock = NET_NewQSocket ();
|
2021-04-04 03:20:01 +00:00
|
|
|
if (sock == NULL) {
|
2001-02-19 21:15:25 +00:00
|
|
|
goto ErrorReturn2;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
sock->socket = newsock;
|
|
|
|
sock->landriver = net_landriverlevel;
|
|
|
|
|
|
|
|
// connect to the host
|
2021-04-04 03:20:01 +00:00
|
|
|
if (dfunc.Connect (newsock, &sendaddr) == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
goto ErrorReturn;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// send the connection request
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("trying...\n");
|
2022-11-02 06:08:09 +00:00
|
|
|
cl.viewstate.time = cl.time;
|
|
|
|
CL_UpdateScreen (&cl.viewstate);
|
2001-02-19 21:15:25 +00:00
|
|
|
start_time = net_time;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
for (reps = 0; reps < 3; reps++) {
|
|
|
|
SZ_Clear (net_message->message);
|
2001-02-19 21:15:25 +00:00
|
|
|
// save space for the header, filled in later
|
2001-02-26 06:48:02 +00:00
|
|
|
MSG_WriteLong (net_message->message, 0);
|
|
|
|
MSG_WriteByte (net_message->message, CCREQ_CONNECT);
|
|
|
|
MSG_WriteString (net_message->message, "QUAKE");
|
|
|
|
MSG_WriteByte (net_message->message, NET_PROTOCOL_VERSION);
|
2021-04-04 08:01:53 +00:00
|
|
|
MSG_PokeLongBE (net_message->message, 0,
|
|
|
|
NETFLAG_CTL | net_message->message->cursize);
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.Write (newsock, net_message->message->data,
|
|
|
|
net_message->message->cursize, &sendaddr);
|
|
|
|
SZ_Clear (net_message->message);
|
|
|
|
do {
|
|
|
|
ret =
|
|
|
|
dfunc.Read (newsock, net_message->message->data,
|
|
|
|
net_message->message->maxsize, &readaddr);
|
2001-02-19 21:15:25 +00:00
|
|
|
// if we got something, validate it
|
2001-02-26 06:48:02 +00:00
|
|
|
if (ret > 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
// is it from the right place?
|
2001-02-26 06:48:02 +00:00
|
|
|
if (sfunc.AddrCompare (&readaddr, &sendaddr) != 0) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "%2d ",
|
2011-08-22 01:30:35 +00:00
|
|
|
sfunc.AddrCompare (&readaddr, &sendaddr));
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "%d %s ", readaddr.family,
|
2011-08-02 08:32:36 +00:00
|
|
|
sfunc.AddrToString (&readaddr));
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "%d %s\n", sendaddr.family,
|
2011-08-02 08:32:36 +00:00
|
|
|
sfunc.AddrToString (&sendaddr));
|
2001-02-19 21:15:25 +00:00
|
|
|
ret = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2003-04-17 00:01:48 +00:00
|
|
|
if (ret < (int) sizeof (int)) {
|
2001-02-19 21:15:25 +00:00
|
|
|
ret = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2001-02-23 23:16:13 +00:00
|
|
|
net_message->message->cursize = ret;
|
|
|
|
MSG_BeginReading (net_message);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-04 08:01:53 +00:00
|
|
|
control = MSG_ReadLongBE (net_message);
|
2001-02-26 06:48:02 +00:00
|
|
|
if (control == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
ret = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2003-04-17 00:01:48 +00:00
|
|
|
if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) {
|
2001-02-19 21:15:25 +00:00
|
|
|
ret = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
if ((control & NETFLAG_LENGTH_MASK) != ret) {
|
2001-02-19 21:15:25 +00:00
|
|
|
ret = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2021-04-04 03:20:01 +00:00
|
|
|
} while (ret == 0 && (SetNetTime () - start_time) < 2.5);
|
|
|
|
|
|
|
|
if (ret) {
|
2001-02-19 21:15:25 +00:00
|
|
|
break;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("still trying...\n");
|
2022-11-02 06:08:09 +00:00
|
|
|
cl.viewstate.time = cl.time;
|
|
|
|
CL_UpdateScreen (&cl.viewstate);
|
2001-02-26 06:48:02 +00:00
|
|
|
start_time = SetNetTime ();
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (ret == 0) {
|
2001-02-19 21:15:25 +00:00
|
|
|
reason = "No Response";
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("%s\n", reason);
|
2001-03-04 07:43:27 +00:00
|
|
|
// strcpy (m_return_reason, reason);
|
2001-02-19 21:15:25 +00:00
|
|
|
goto ErrorReturn;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (ret == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
reason = "Network Error";
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("%s\n", reason);
|
2001-03-04 07:43:27 +00:00
|
|
|
// strcpy (m_return_reason, reason);
|
2001-02-19 21:15:25 +00:00
|
|
|
goto ErrorReturn;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
ret = MSG_ReadByte (net_message);
|
|
|
|
if (ret == CCREP_REJECT) {
|
|
|
|
reason = MSG_ReadString (net_message);
|
2009-04-10 23:59:48 +00:00
|
|
|
Sys_Printf ("%s\n", reason);
|
2001-03-04 07:43:27 +00:00
|
|
|
// strncpy (m_return_reason, reason, 31);
|
2001-02-19 21:15:25 +00:00
|
|
|
goto ErrorReturn;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (ret == CCREP_ACCEPT) {
|
2011-09-04 00:00:42 +00:00
|
|
|
memcpy (&sock->addr, &sendaddr, sizeof (netadr_t));
|
2001-02-26 06:48:02 +00:00
|
|
|
dfunc.SetSocketPort (&sock->addr, MSG_ReadLong (net_message));
|
|
|
|
} else {
|
2001-02-19 21:15:25 +00:00
|
|
|
reason = "Bad Response";
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("%s\n", reason);
|
2001-03-04 07:43:27 +00:00
|
|
|
// strcpy (m_return_reason, reason);
|
2001-02-19 21:15:25 +00:00
|
|
|
goto ErrorReturn;
|
|
|
|
}
|
|
|
|
|
|
|
|
dfunc.GetNameFromAddr (&sendaddr, sock->address);
|
|
|
|
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("Connection accepted\n");
|
2001-02-26 06:48:02 +00:00
|
|
|
sock->lastMessageTime = SetNetTime ();
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// switch the connection to the specified address
|
2001-02-26 06:48:02 +00:00
|
|
|
if (dfunc.Connect (newsock, &sock->addr) == -1) {
|
2001-02-19 21:15:25 +00:00
|
|
|
reason = "Connect to Game failed";
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("%s\n", reason);
|
2001-03-04 07:43:27 +00:00
|
|
|
// strcpy (m_return_reason, reason);
|
2001-02-19 21:15:25 +00:00
|
|
|
goto ErrorReturn;
|
|
|
|
}
|
|
|
|
|
2001-03-04 07:43:27 +00:00
|
|
|
// FIXME: MENUCODE
|
|
|
|
// m_return_onerror = false;
|
2001-02-19 21:15:25 +00:00
|
|
|
return sock;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
ErrorReturn:
|
2001-03-04 07:43:27 +00:00
|
|
|
// FIXME: MENUCODE - do something with reason
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_net, "FIXME: MENUCODE - do something with reason\n");
|
2001-02-26 06:48:02 +00:00
|
|
|
NET_FreeQSocket (sock);
|
|
|
|
ErrorReturn2:
|
|
|
|
dfunc.CloseSocket (newsock);
|
2001-03-04 07:43:27 +00:00
|
|
|
// FIXME: MENUCODE
|
|
|
|
// if (m_return_onerror) {
|
|
|
|
// key_dest = key_menu;
|
|
|
|
// m_state = m_return_state;
|
|
|
|
// m_return_onerror = false;
|
|
|
|
// }
|
2001-02-19 21:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
qsocket_t *
|
2001-07-15 07:04:17 +00:00
|
|
|
Datagram_Connect (const char *host)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
qsocket_t *ret = NULL;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers;
|
2021-04-04 03:20:01 +00:00
|
|
|
net_landriverlevel++) {
|
|
|
|
if (net_landrivers[net_landriverlevel].initialized) {
|
|
|
|
if ((ret = _Datagram_Connect (host)) != NULL) {
|
2001-02-19 21:15:25 +00:00
|
|
|
break;
|
2021-04-04 03:20:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
return ret;
|
|
|
|
}
|