int serverlist_sortflags;
int serverlist_viewcount = 0;
-serverlist_entry_t *serverlist_viewlist[SERVERLIST_VIEWLISTSIZE];
+unsigned short serverlist_viewlist[SERVERLIST_VIEWLISTSIZE];
-int serverlist_cachecount;
-serverlist_entry_t serverlist_cache[SERVERLIST_TOTALSIZE];
+int serverlist_maxcachecount = 0;
+int serverlist_cachecount = 0;
+serverlist_entry_t *serverlist_cache = NULL;
qboolean serverlist_consoleoutput;
static int nFavorites = 0;
-static lhnetaddress_t favorites[256];
+static lhnetaddress_t favorites[MAX_FAVORITESERVERS];
void NetConn_UpdateFavorites(void)
{
for( ; i > index ; i-- )
serverlist_viewlist[ i ] = serverlist_viewlist[ i - 1 ];
- serverlist_viewlist[index] = entry;
+ serverlist_viewlist[index] = (int)(entry - serverlist_cache);
}
/// we suppose serverlist_viewcount to be valid, ie > 0
// two special cases
// check whether to insert it as new first item
- if( _ServerList_Entry_Compare( entry, serverlist_viewlist[0] ) ) {
+ if( _ServerList_Entry_Compare( entry, ServerList_GetViewEntry(0) ) ) {
_ServerList_ViewList_Helper_InsertBefore( 0, entry );
return;
} // check whether to insert it as new last item
- else if( !_ServerList_Entry_Compare( entry, serverlist_viewlist[serverlist_viewcount - 1] ) ) {
+ else if( !_ServerList_Entry_Compare( entry, ServerList_GetViewEntry(serverlist_viewcount - 1) ) ) {
_ServerList_ViewList_Helper_InsertBefore( serverlist_viewcount, entry );
return;
}
{
mid = (start + end) / 2;
// test the item that lies in the middle between start and end
- if( _ServerList_Entry_Compare( entry, serverlist_viewlist[mid] ) )
+ if( _ServerList_Entry_Compare( entry, ServerList_GetViewEntry(mid) ) )
// the item has to be in the upper half
end = mid;
else
int i;
for( i = 0; i < serverlist_viewcount; i++ )
{
- if (serverlist_viewlist[i] == entry)
+ if (ServerList_GetViewEntry(i) == entry)
{
_ServerList_ViewList_Helper_Remove(i);
break;
static void _ServerList_Test(void)
{
int i;
+ if (serverlist_maxcachecount <= 1024)
+ {
+ serverlist_maxcachecount = 1024;
+ serverlist_cache = (serverlist_entry_t *)Mem_Realloc(netconn_mempool, (void *)serverlist_cache, sizeof(serverlist_entry_t) * serverlist_maxcachecount);
+ }
for( i = 0 ; i < 1024 ; i++ ) {
memset( &serverlist_cache[serverlist_cachecount], 0, sizeof( serverlist_entry_t ) );
serverlist_cache[serverlist_cachecount].info.ping = 1000 + 1024 - i;
serverreplycount = 0;
serverlist_cachecount = 0;
serverlist_viewcount = 0;
+ serverlist_maxcachecount = 0;
+ serverlist_cache = (serverlist_entry_t *)Mem_Realloc(netconn_mempool, (void *)serverlist_cache, sizeof(serverlist_entry_t) * serverlist_maxcachecount);
} else {
// refresh all entries
int n;
int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolversion_t protocol, int rate, qboolean quakesignon_suppressreliables)
{
int totallen = 0;
- int temp;
// if this packet was supposedly choked, but we find ourselves sending one
// anyway, make sure the size counting starts at zero
sendreliable = true;
}
// outgoing unreliable packet number, and outgoing reliable packet number (0 or 1)
- temp = (unsigned int)conn->outgoing_unreliable_sequence | ((unsigned int)sendreliable<<31);
- *((int *)(sendbuffer + 0)) = LittleLong(temp);
+ StoreLittleLong(sendbuffer, (unsigned int)conn->outgoing_unreliable_sequence | ((unsigned int)sendreliable<<31));
// last received unreliable packet number, and last received reliable packet number (0 or 1)
- temp = (unsigned int)conn->qw.incoming_sequence | ((unsigned int)conn->qw.incoming_reliable_sequence<<31);
- *((int *)(sendbuffer + 4)) = LittleLong(temp);
+ StoreLittleLong(sendbuffer + 4, (unsigned int)conn->qw.incoming_sequence | ((unsigned int)conn->qw.incoming_reliable_sequence<<31));
packetLen = 8;
conn->outgoing_unreliable_sequence++;
// client sends qport in every packet
{
cl_sockets[cl_numsockets++] = s;
LHNETADDRESS_ToString(LHNET_AddressFromSocket(s), addressstring2, sizeof(addressstring2), true);
- Con_Printf("Client opened a socket on address %s\n", addressstring2);
+ if (addresstype != LHNETADDRESSTYPE_LOOP)
+ Con_Printf("Client opened a socket on address %s\n", addressstring2);
}
else
{
Con_Printf("Client using port %i\n", port);
NetConn_OpenClientPort(NULL, LHNETADDRESSTYPE_LOOP, 2);
NetConn_OpenClientPort(net_address.string, LHNETADDRESSTYPE_INET4, port);
+#ifdef SUPPORTIPV6
NetConn_OpenClientPort(net_address_ipv6.string, LHNETADDRESSTYPE_INET6, port);
+#endif
}
void NetConn_CloseServerPorts(void)
{
sv_sockets[sv_numsockets++] = s;
LHNETADDRESS_ToString(LHNET_AddressFromSocket(s), addressstring2, sizeof(addressstring2), true);
- Con_Printf("Server listening on address %s\n", addressstring2);
+ if (addresstype != LHNETADDRESSTYPE_LOOP)
+ Con_Printf("Server listening on address %s\n", addressstring2);
return true;
}
else
NetConn_OpenServerPort(NULL, LHNETADDRESSTYPE_LOOP, 1, 1);
if (opennetports)
{
+#ifdef SUPPORTIPV6
qboolean ip4success = NetConn_OpenServerPort(net_address.string, LHNETADDRESSTYPE_INET4, port, 100);
NetConn_OpenServerPort(net_address_ipv6.string, LHNETADDRESSTYPE_INET6, port, ip4success ? 1 : 100);
+#else
+ NetConn_OpenServerPort(net_address.string, LHNETADDRESSTYPE_INET4, port, 100);
+#endif
}
if (sv_numsockets == 0)
Host_Error("NetConn_OpenServerPorts: unable to open any ports!");
int sequence, sequence_ack;
int reliable_ack, reliable_message;
int count;
- int qport;
+ //int qport;
sequence = LittleLong(*((int *)(data + 0)));
sequence_ack = LittleLong(*((int *)(data + 4)));
if (length < 2)
return 0;
// TODO: use qport to identify that this client really is who they say they are? (and elsewhere in the code to identify the connection without a port match?)
- qport = LittleShort(*((int *)(data + 8)));
+ //qport = LittleShort(*((int *)(data + 8)));
data += 2;
length -= 2;
}
if (serverlist_cachecount == SERVERLIST_TOTALSIZE)
return -1;
+ if (serverlist_maxcachecount <= serverlist_cachecount)
+ {
+ serverlist_maxcachecount += 64;
+ serverlist_cache = (serverlist_entry_t *)Mem_Realloc(netconn_mempool, (void *)serverlist_cache, sizeof(serverlist_entry_t) * serverlist_maxcachecount);
+ }
entry = &serverlist_cache[n];
memset(entry, 0, sizeof(*entry));
if( !strcmp( ipstring, serverlist_cache[ n ].info.cname ) )
break;
- entry = &serverlist_cache[n];
-
if( n < serverlist_cachecount ) {
// the entry has already been queried once or
return true;
}
+ if (serverlist_maxcachecount <= n)
+ {
+ serverlist_maxcachecount += 64;
+ serverlist_cache = (serverlist_entry_t *)Mem_Realloc(netconn_mempool, (void *)serverlist_cache, sizeof(serverlist_entry_t) * serverlist_maxcachecount);
+ }
+
+ entry = &serverlist_cache[n];
+
memset(entry, 0, sizeof(entry));
entry->protocol = protocol;
// store the data the engine cares about (address and ping)
if (length > 10 && !memcmp(string, "challenge ", 10) && cls.rcon_trying)
{
- int i, j;
+ int i = 0, j;
for (j = 0;j < MAX_RCONS;j++)
{
+ // note: this value from i is used outside the loop too...
i = (cls.rcon_ringpos + j) % MAX_RCONS;
if(cls.rcon_commands[i][0])
if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[i]))
if(HMAC_MDFOUR_16BYTES((unsigned char *) (buf + 29), (unsigned char *) argbuf, strlen(argbuf), (unsigned char *) rcon_password.string, n))
{
+ int k;
buf[45] = ' ';
strlcpy(buf + 46, argbuf, sizeof(buf) - 46);
NetConn_Write(mysocket, buf, 46 + strlen(buf + 46), peeraddress);
cls.rcon_commands[i][0] = 0;
--cls.rcon_trying;
- for (i = 0;i < MAX_RCONS;i++)
- if(cls.rcon_commands[i][0])
- if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[i]))
+ for (k = 0;k < MAX_RCONS;k++)
+ if(cls.rcon_commands[k][0])
+ if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[k]))
break;
- if(i < MAX_RCONS)
+ if(k < MAX_RCONS)
{
+ int l;
NetConn_WriteString(mysocket, "\377\377\377\377getchallenge", peeraddress);
// extend the timeout on other requests as we asked for a challenge
- for (i = 0;i < MAX_RCONS;i++)
- if(cls.rcon_commands[i][0])
- if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[i]))
- cls.rcon_timeout[i] = realtime + rcon_secure_challengetimeout.value;
+ for (l = 0;l < MAX_RCONS;l++)
+ if(cls.rcon_commands[l][0])
+ if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[l]))
+ cls.rcon_timeout[l] = realtime + rcon_secure_challengetimeout.value;
}
return true; // we used up the challenge, so we can't use this oen for connecting now anyway
// darkplaces or quake3
char protocolnames[1400];
Protocol_Names(protocolnames, sizeof(protocolnames));
- Con_Printf("\"%s\" received, sending connect request back to %s\n", string, addressstring2);
+ Con_DPrintf("\"%s\" received, sending connect request back to %s\n", string, addressstring2);
M_Update_Return_Reason("Got challenge response");
// update the server IP in the userinfo (QW servers expect this, and it is used by the reconnect command)
InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2);
}
if (!strncmp(string, "ping", 4))
{
- if (developer.integer >= 10)
- Con_Printf("Received ping from %s, sending ack\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Received ping from %s, sending ack\n", addressstring2);
NetConn_WriteString(mysocket, "\377\377\377\377ack", peeraddress);
return true;
}
switch (c)
{
case CCREP_ACCEPT:
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: received CCREP_ACCEPT from %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: received CCREP_ACCEPT from %s.\n", addressstring2);
if (cls.connect_trying)
{
lhnetaddress_t clientportaddress;
}
break;
case CCREP_REJECT:
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: received CCREP_REJECT from %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: received CCREP_REJECT from %s.\n", addressstring2);
cls.connect_trying = false;
M_Update_Return_Reason((char *)MSG_ReadString());
break;
case CCREP_SERVER_INFO:
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: received CCREP_SERVER_INFO from %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: received CCREP_SERVER_INFO from %s.\n", addressstring2);
// LordHavoc: because the quake server may report weird addresses
// we just ignore it and keep the real address
MSG_ReadString();
break;
case CCREP_RCON: // RocketGuy: ProQuake rcon support
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: received CCREP_RCON from %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: received CCREP_RCON from %s.\n", addressstring2);
Con_Printf("%s\n", MSG_ReadString());
break;
case CCREP_PLAYER_INFO:
// we got a CCREP_PLAYER_INFO??
- //if (developer.integer >= 10)
+ //if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: received CCREP_PLAYER_INFO from %s.\n", addressstring2);
break;
case CCREP_RULE_INFO:
// we got a CCREP_RULE_INFO??
- //if (developer.integer >= 10)
+ //if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: received CCREP_RULE_INFO from %s.\n", addressstring2);
break;
default:
SZ_Clear(&net_message);
}
for (i = 0;i < cl_numsockets;i++)
+ {
while (cl_sockets[i] && (length = NetConn_Read(cl_sockets[i], readbuffer, sizeof(readbuffer), &peeraddress)) > 0)
+ {
+// R_TimeReport("clientreadnetwork");
NetConn_ClientParsePacket(cl_sockets[i], readbuffer, length, &peeraddress);
+// R_TimeReport("clientparsepacket");
+ }
+ }
NetConn_QueryQueueFrame();
if (cls.netcon && realtime > cls.netcon->timeout && !sv.active)
{
"%s",
fullstatus ? "statusResponse" : "infoResponse",
gamename, com_modname, gameversion.integer, svs.maxclients,
- nb_clients, nb_bots, sv.name, hostname.string, NET_PROTOCOL_VERSION,
+ nb_clients, nb_bots, sv.worldbasename, hostname.string, NET_PROTOCOL_VERSION,
*qcstatus ? "\\qcstatus\\" : "", qcstatus,
challenge ? "\\challenge\\" : "", challenge ? challenge : "",
fullstatus ? "\n" : "");
const char *RCon_Authenticate(lhnetaddress_t *peeraddress, const char *password, const char *s, const char *endpos, rcon_matchfunc_t comparator, const char *cs, int cslen)
{
const char *text, *userpass_start, *userpass_end, *userpass_startpass;
- char buf[MAX_INPUTLINE];
+ static char buf[MAX_INPUTLINE];
qboolean hasquotes;
qboolean restricted = false;
qboolean have_usernames = false;
userpass_startpass = strchr(userpass_start, ':');
if(have_usernames && userpass_startpass && userpass_startpass < userpass_end)
return va("%srcon (username %.*s)", restricted ? "restricted " : "", (int)(userpass_startpass-userpass_start), userpass_start);
- else
- return va("%srcon", restricted ? "restricted " : "");
- return "restricted rcon";
+ return va("%srcon", restricted ? "restricted " : "");
}
void RCon_Execute(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, const char *addressstring2, const char *userlevel, const char *s, const char *endpos)
int i, ret, clientnum, best;
double besttime;
client_t *client;
- char *s, *string, response[1400], addressstring2[128], stringbuf[16384];
+ char *s, *string, response[1400], addressstring2[128];
+ static char stringbuf[16384];
qboolean islocal = (LHNETADDRESS_GetAddressType(peeraddress) == LHNETADDRESSTYPE_LOOP);
if (!sv.active)
stringbuf[length] = 0;
string = stringbuf;
- if (developer.integer >= 10)
+ if (developer_extra.integer)
{
Con_Printf("NetConn_ServerParsePacket: %s sent us a command:\n", addressstring2);
Com_HexDumpToConsole(data, length);
// check engine protocol
if(!(s = SearchInfostring(string, "protocol")) || strcmp(s, "darkplaces 3"))
{
- if (developer.integer >= 10)
+ if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: sending \"reject Wrong game protocol.\" to %s.\n", addressstring2);
NetConn_WriteString(mysocket, "\377\377\377\377reject Wrong game protocol.", peeraddress);
return true;
{
// client crashed and is coming back,
// keep their stuff intact
- if (developer.integer >= 10)
+ if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: sending \"accept\" to %s.\n", addressstring2);
NetConn_WriteString(mysocket, "\377\377\377\377accept", peeraddress);
SV_VM_Begin();
{
// client is still trying to connect,
// so we send a duplicate reply
- if (developer.integer >= 10)
+ if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: sending duplicate accept to %s.\n", addressstring2);
NetConn_WriteString(mysocket, "\377\377\377\377accept", peeraddress);
}
if (!client->active && (conn = NetConn_Open(mysocket, peeraddress)))
{
// allocated connection
- if (developer.integer >= 10)
+ if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: sending \"accept\" to %s.\n", conn->address);
NetConn_WriteString(mysocket, "\377\377\377\377accept", peeraddress);
// now set up the client
}
// no empty slots found - server is full
- if (developer.integer >= 10)
+ if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: sending \"reject Server is full.\" to %s.\n", addressstring2);
NetConn_WriteString(mysocket, "\377\377\377\377reject Server is full.", peeraddress);
if (NetConn_BuildStatusResponse(challenge, response, sizeof(response), false))
{
- if (developer.integer >= 10)
- Con_Printf("Sending reply to master %s - %s\n", addressstring2, response);
+ if (developer_extra.integer)
+ Con_DPrintf("Sending reply to master %s - %s\n", addressstring2, response);
NetConn_WriteString(mysocket, response, peeraddress);
}
return true;
if (NetConn_BuildStatusResponse(challenge, response, sizeof(response), true))
{
- if (developer.integer >= 10)
- Con_Printf("Sending reply to client %s - %s\n", addressstring2, response);
+ if (developer_extra.integer)
+ Con_DPrintf("Sending reply to client %s - %s\n", addressstring2, response);
NetConn_WriteString(mysocket, response, peeraddress);
}
return true;
}
if (!strncmp(string, "ping", 4))
{
- if (developer.integer >= 10)
- Con_Printf("Received ping from %s, sending ack\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Received ping from %s, sending ack\n", addressstring2);
NetConn_WriteString(mysocket, "\377\377\377\377ack", peeraddress);
return true;
}
switch (c)
{
case CCREQ_CONNECT:
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: received CCREQ_CONNECT from %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_CONNECT from %s.\n", addressstring2);
if(!islocal && sv_public.integer <= -2)
break;
protocolnumber = MSG_ReadByte();
if (strcmp(protocolname, "QUAKE") || protocolnumber != NET_PROTOCOL_VERSION)
{
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Incompatible version.\" to %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Incompatible version.\" to %s.\n", addressstring2);
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
// (if so, keep their stuff intact)
// send a reply
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: sending duplicate CCREP_ACCEPT to %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: sending duplicate CCREP_ACCEPT to %s.\n", addressstring2);
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
// connect to the client
// everything is allocated, just fill in the details
strlcpy (conn->address, addressstring2, sizeof (conn->address));
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: sending CCREP_ACCEPT to %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_ACCEPT to %s.\n", addressstring2);
// send back the info about the server connection
SZ_Clear(&net_message);
// save space for the header, filled in later
}
}
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Server is full.\" to %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Server is full.\" to %s.\n", addressstring2);
// no room; try to let player know
SZ_Clear(&net_message);
// save space for the header, filled in later
SZ_Clear(&net_message);
break;
case CCREQ_SERVER_INFO:
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: received CCREQ_SERVER_INFO from %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_SERVER_INFO from %s.\n", addressstring2);
if(!islocal && sv_public.integer <= -1)
break;
if (sv.active && !strcmp(MSG_ReadString(), "QUAKE"))
{
int numclients;
char myaddressstring[128];
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: sending CCREP_SERVER_INFO to %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_SERVER_INFO to %s.\n", addressstring2);
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
}
break;
case CCREQ_PLAYER_INFO:
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: received CCREQ_PLAYER_INFO from %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_PLAYER_INFO from %s.\n", addressstring2);
if(!islocal && sv_public.integer <= -1)
break;
if (sv.active)
}
break;
case CCREQ_RULE_INFO:
- if (developer.integer >= 10)
- Con_Printf("Datagram_ParseConnectionless: received CCREQ_RULE_INFO from %s.\n", addressstring2);
+ if (developer_extra.integer)
+ Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_RULE_INFO from %s.\n", addressstring2);
if(!islocal && sv_public.integer <= -1)
break;
if (sv.active)