Add support for Q2E's lan networking layer (the annoying lobby bit).
This is separate from protocol 2023 stuff.
This commit is contained in:
parent
3357338ab7
commit
969134d9fd
8 changed files with 1145 additions and 158 deletions
|
@ -310,6 +310,7 @@ static struct
|
|||
CIM_DEFAULT, //sends both a qw getchallenge and nq connect (also with postfixed getchallenge so modified servers can force getchallenge)
|
||||
CIM_NQONLY, //disables getchallenge (so fte servers treat us as an nq client). should not be used for dpp7 servers.
|
||||
CIM_QEONLY, //forces dtls and uses a different nq netchan version
|
||||
CIM_Q2EONLY, //forces dtls and uses a different nq netchan version
|
||||
} mode;
|
||||
enum coninfospec_e
|
||||
{
|
||||
|
@ -825,6 +826,12 @@ char *CL_TryingToConnect(void)
|
|||
if (!connectinfo.trying)
|
||||
return NULL;
|
||||
|
||||
if (connectinfo.numadr >= 1 && connectinfo.adr[0].prot == NP_KEXLAN)
|
||||
{
|
||||
char status[1024];
|
||||
if (NET_GetConnectionCertificate(cls.sockets, &connectinfo.adr[0], QCERT_LOBBYSTATUS, status, sizeof(status))>0)
|
||||
return va("%s\n%s", cls.servername, status);
|
||||
}
|
||||
return cls.servername;
|
||||
}
|
||||
|
||||
|
@ -870,6 +877,15 @@ static void CL_ResolvedServer(void *vctx, void *data, size_t a, size_t b)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (connectinfo.mode == CIM_Q2EONLY)
|
||||
{
|
||||
for (i = 0; i < ctx->found; i++)
|
||||
{ //if we've already established a dtls connection, stick with it
|
||||
if (ctx->adr[i].prot == NP_DGRAM)
|
||||
ctx->adr[i].prot = NP_KEXLAN;
|
||||
}
|
||||
}
|
||||
|
||||
connectinfo.numadr = ctx->found;
|
||||
connectinfo.nextadr = 0;
|
||||
connectinfo.resolving = false;
|
||||
|
@ -889,7 +905,7 @@ static void CL_ResolveServer(void *vctx, void *data, size_t a, size_t b)
|
|||
|
||||
COM_AddWork(WG_MAIN, CL_ResolvedServer, ctx, data, a, b);
|
||||
}
|
||||
static qboolean CL_IsPendingServerAddress(netadr_t *adr)
|
||||
qboolean CL_IsPendingServerAddress(netadr_t *adr)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < connectinfo.numadr; i++)
|
||||
|
@ -1313,7 +1329,9 @@ void CL_CheckForResend (void)
|
|||
if (to->prot == NP_DGRAM)
|
||||
connectinfo.nextadr++; //cycle hosts with each ping (if we got multiple).
|
||||
|
||||
if (connectinfo.mode==CIM_QEONLY || connectinfo.mode==CIM_NQONLY)
|
||||
if (connectinfo.mode==CIM_Q2EONLY)
|
||||
contype |= 1; //don't ever try nq packets here.
|
||||
else if (connectinfo.mode==CIM_QEONLY || connectinfo.mode==CIM_NQONLY)
|
||||
contype |= 2;
|
||||
else
|
||||
{
|
||||
|
@ -1321,7 +1339,16 @@ void CL_CheckForResend (void)
|
|||
#ifdef VM_UI
|
||||
if (!(q3&&q3->ui.IsRunning())) //don't try to connect to nq servers when running a q3ui. I was getting annoying error messages from q3 servers due to this.
|
||||
#endif
|
||||
contype |= 2; /*try nq connections periodically (or if its the default nq port)*/
|
||||
{
|
||||
COM_Parse(com_protocolname.string);
|
||||
if (!strcmp(com_token, "Quake2"))
|
||||
{
|
||||
if (connectinfo.nextadr>3) //don't create an extra channel until we know our preferred one has failed.
|
||||
contype |= 4; /*q2e's kex lan layer*/
|
||||
}
|
||||
else
|
||||
contype |= 2; /*try nq connections periodically (or if its the default nq port)*/
|
||||
}
|
||||
}
|
||||
|
||||
/*DP, QW, Q2, Q3*/
|
||||
|
@ -1401,6 +1428,15 @@ void CL_CheckForResend (void)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef Q2CLIENT
|
||||
if ((contype & 4) && !connectinfo.clogged)
|
||||
{
|
||||
#define KEXLAN_SHAMELESSSELFPROMOMAGIC "\x08""CRANTIME" //hey, if you can't shove your own nick in your network protocols then you're doing it wrong.
|
||||
#define KEXLAN_SUBPROTOCOL "\x08""Quake II" //this should be cvar-ised at some point, if its to ever be useful for anything but q2.
|
||||
static char pkt[] = "\x01\x60\x80"KEXLAN_SHAMELESSSELFPROMOMAGIC KEXLAN_SUBPROTOCOL"\x01";
|
||||
NET_SendPacket (cls.sockets, strlen(pkt), pkt, to);
|
||||
}
|
||||
#endif
|
||||
|
||||
connectinfo.tries++;
|
||||
|
||||
|
@ -1429,30 +1465,25 @@ static void CL_BeginServerConnect(char *host, int port, qboolean noproxy, enum c
|
|||
|
||||
if (schemeend)
|
||||
{
|
||||
//"qw:tcp://host/observe"
|
||||
const char *schemestart = strchr(host, ':');
|
||||
int schemelen;
|
||||
//if its one of our explicit protocols then use the url as-is
|
||||
const char *netschemes[] = {"udp", "udp4", "udp6", "ipx", "tcp", "tcp4", "tcp6", /*ipx*/"spx", "ws", "wss", "tls", "dtls", "ice", "rtc", "ices", "rtcs", "irc", "udg", "unix"};
|
||||
int i;
|
||||
size_t slen;
|
||||
const struct urischeme_s *scheme;
|
||||
|
||||
if (!schemestart || schemestart==schemeend)
|
||||
schemestart = host;
|
||||
else
|
||||
schemestart++;
|
||||
schemelen = schemeend-schemestart;
|
||||
|
||||
Q_strncpyz (cls.servername, "", sizeof(cls.servername));
|
||||
for (i = 0; i < countof(netschemes); i++)
|
||||
//the scheme is either a network scheme in which case we use it directly, or a game-specific scheme.
|
||||
scheme = NET_IsURIScheme(schemestart);
|
||||
if (scheme->prot == NP_INVALID)
|
||||
scheme = NULL; //qw:// or q3:// something that's just noise here.
|
||||
if (scheme->flags&URISCHEME_NEEDSRESOURCE)
|
||||
{
|
||||
slen = strlen(netschemes[i]);
|
||||
if (schemelen == slen && !strncmp(schemestart, netschemes[i], slen))
|
||||
{
|
||||
Q_strncpyz (cls.servername, host, sizeof(cls.servername)); //oh. will probably be okay then
|
||||
break;
|
||||
}
|
||||
Q_strncpyz (cls.servername, schemestart, sizeof(cls.servername)); //oh. will probably be okay then
|
||||
arglist = NULL;
|
||||
}
|
||||
if (!*cls.servername)
|
||||
else
|
||||
{ //not some '/foo' name, not rtc:// either...
|
||||
char *sl = strchr(schemeend+3, '/');
|
||||
if (sl)
|
||||
|
@ -1479,7 +1510,11 @@ static void CL_BeginServerConnect(char *host, int port, qboolean noproxy, enum c
|
|||
memmove(sl, sl+1, strlen(sl+1)+1);
|
||||
}
|
||||
}
|
||||
Q_strncpyz (cls.servername, schemeend+3, sizeof(cls.servername)); //probably some game-specific mess that we don't know
|
||||
if (scheme) //preserve the scheme, the netchan cares.
|
||||
Q_strncpyz (cls.servername, schemestart, sizeof(cls.servername)); //probably some game-specific mess that we don't know
|
||||
else
|
||||
Q_strncpyz (cls.servername, schemeend+3, sizeof(cls.servername)); //probably some game-specific mess that we don't know
|
||||
arglist = strchr(cls.servername, '?');
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1491,10 +1526,9 @@ static void CL_BeginServerConnect(char *host, int port, qboolean noproxy, enum c
|
|||
Q_strncpyz (cls.servername, host, sizeof(cls.servername));
|
||||
else
|
||||
Q_snprintfz(cls.servername, sizeof(cls.servername), "%s@%s", host, cl_proxyaddr.string);
|
||||
arglist = strchr(cls.servername, '?');
|
||||
}
|
||||
|
||||
arglist = strchr(cls.servername, '?');
|
||||
|
||||
if (!port)
|
||||
port = cl_defaultport.value;
|
||||
|
||||
|
@ -1748,6 +1782,7 @@ void CLNQ_Connect_f (void)
|
|||
{
|
||||
char *server;
|
||||
enum coninfomode_e mode;
|
||||
int port = 26000;
|
||||
|
||||
if (Cmd_Argc() != 2)
|
||||
{
|
||||
|
@ -1765,7 +1800,26 @@ void CLNQ_Connect_f (void)
|
|||
|
||||
CL_Disconnect_f ();
|
||||
|
||||
CL_BeginServerConnect(server, 26000, true, mode, CIS_DEFAULT/*doesn't really do spec/join stuff, but if the server asks for our info later...*/);
|
||||
CL_BeginServerConnect(server, port, true, mode, CIS_DEFAULT/*doesn't really do spec/join stuff, but if the server asks for our info later...*/);
|
||||
}
|
||||
#endif
|
||||
#ifdef Q2CLIENT
|
||||
void CLQ2E_Connect_f (void)
|
||||
{
|
||||
char *server;
|
||||
|
||||
if (Cmd_Argc() != 2)
|
||||
{
|
||||
Con_TPrintf ("usage: connect <server>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
server = Cmd_Argv (1);
|
||||
server = strcpy(alloca(strlen(server)+1), server);
|
||||
|
||||
CL_Disconnect_f ();
|
||||
|
||||
CL_BeginServerConnect(server, PORT_Q2EXSERVER/*q2e servers ignore their own port cvar, so don't use the standard q2 port number here*/, true, CIM_Q2EONLY, CIS_DEFAULT);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3564,6 +3618,7 @@ void CL_Reconnect_f (void)
|
|||
|
||||
static void CL_ConnectionlessPacket_Connection(char *tokens)
|
||||
{
|
||||
int qportsize = -1;
|
||||
if (net_from.type == NA_INVALID)
|
||||
return; //I've found a qizmo demo that contains one of these. its best left ignored.
|
||||
|
||||
|
@ -3601,8 +3656,10 @@ static void CL_ConnectionlessPacket_Connection(char *tokens)
|
|||
}
|
||||
|
||||
#if defined(Q2CLIENT)
|
||||
if (tokens)
|
||||
if (tokens && cls.protocol == CP_QUAKE2)
|
||||
{
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
|
||||
qportsize = 1;
|
||||
tokens = COM_Parse(tokens); //skip the client_connect bit
|
||||
while((tokens = COM_Parse(tokens)))
|
||||
{
|
||||
|
@ -3615,16 +3672,9 @@ static void CL_ConnectionlessPacket_Connection(char *tokens)
|
|||
}
|
||||
}
|
||||
else if (!strncmp(com_token, "nc=", 3))
|
||||
{
|
||||
int type = (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)?1:0;
|
||||
if (atoi(com_token+3) != type)
|
||||
{
|
||||
CL_ConnectAbort("server's netchan type differs from expected.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
qportsize = atoi(com_token+3)?1:2;
|
||||
else if (!strncmp(com_token, "map=", 4))
|
||||
;
|
||||
SCR_ImageName(com_token+4);
|
||||
else if (!strncmp(com_token, "dlserver=", 9))
|
||||
Q_strncpyz(cls.downloadurl, com_token+9, sizeof(cls.downloadurl));
|
||||
else
|
||||
|
@ -3642,12 +3692,9 @@ static void CL_ConnectionlessPacket_Connection(char *tokens)
|
|||
cls.ezprotocolextensions1 = connectinfo.ext.ez1;
|
||||
cls.challenge = connectinfo.challenge;
|
||||
Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, connectinfo.qport);
|
||||
if (cls.protocol == CP_QUAKE2)
|
||||
{
|
||||
cls.protocol_q2 = connectinfo.subprotocol;
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
|
||||
cls.netchan.qportsize = 1;
|
||||
}
|
||||
cls.protocol_q2 = (cls.protocol == CP_QUAKE2)?connectinfo.subprotocol:0;
|
||||
if (qportsize>=0)
|
||||
cls.netchan.qportsize = qportsize;
|
||||
cls.netchan.pext_fragmentation = connectinfo.ext.mtu?true:false;
|
||||
cls.netchan.pext_stunaware = !!(connectinfo.ext.fte2&PEXT2_STUNAWARE);
|
||||
if (connectinfo.ext.mtu >= 64)
|
||||
|
@ -5685,6 +5732,9 @@ void CL_Init (void)
|
|||
#ifdef NQPROT
|
||||
Cmd_AddCommandD ("connectnq", CLNQ_Connect_f, "Connects to the specified server, defaulting to port "STRINGIFY(PORT_NQSERVER)". Also disables QW/Q2/Q3/DP handshakes preventing them from being favoured, so should only be used when you actually want NQ protocols specifically.");
|
||||
Cmd_AddCommandD ("connectqe", CLNQ_Connect_f, "Connects to the specified server, defaulting to port "STRINGIFY(PORT_NQSERVER)". Also forces the use of DTLS and QE-specific handshakes. You will also need to ensure the dtls_psk_* cvars are set properly or the server will refuse the connection.");
|
||||
#endif
|
||||
#ifdef Q2CLIENT
|
||||
Cmd_AddCommandD ("connectq2e", CLQ2E_Connect_f, "Connects to the specified server, defaulting to port "STRINGIFY(PORT_Q2ESERVER)".");
|
||||
#endif
|
||||
Cmd_AddCommand ("reconnect", CL_Reconnect_f);
|
||||
Cmd_AddCommandAD ("join", CL_Join_f, CL_Connect_c, "Switches away from spectator mode, optionally connecting to a different server.");
|
||||
|
|
|
@ -1671,6 +1671,8 @@ int CLNQ_GetMessage (void);
|
|||
#endif
|
||||
|
||||
void CL_BeginServerReconnect(void);
|
||||
qboolean CL_IsPendingServerAddress(netadr_t *adr);
|
||||
void CL_Transfer(netadr_t *adr);
|
||||
|
||||
void SV_User_f (void); //called by client version of the function
|
||||
void SV_Serverinfo_f (void);
|
||||
|
|
|
@ -3871,6 +3871,11 @@ void CL_Say (qboolean team, char *extra)
|
|||
strlcat (sendtext, va("\x7f!%c", 'A'+pv->playernum), sizeof(sendtext));
|
||||
}
|
||||
|
||||
#ifdef Q2CLIENT
|
||||
if (cls.netchan.remote_address.prot == NP_KEXLAN && NET_GetConnectionCertificate(cls.sockets, &cls.netchan.remote_address, QCERT_LOBBYSENDCHAT, sendtext, strlen(sendtext))>0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef Q3CLIENT
|
||||
if (cls.protocol == CP_QUAKE3)
|
||||
q3->cl.SendClientCommand("%s %s%s", team ? "say_team" : "say", extra?extra:"", sendtext);
|
||||
|
|
|
@ -397,7 +397,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#undef USE_EGL
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GNUTLS) || defined(HAVE_WINSSPI)
|
||||
#if defined(HAVE_GNUTLS) || defined(HAVE_WINSSPI) || defined(HAVE_PLUGINS)
|
||||
#define HAVE_SSL
|
||||
#endif
|
||||
#if defined(HAVE_GNUTLS) || defined(HAVE_WINSSPI) || defined(HAVE_PLUGINS)
|
||||
|
|
|
@ -54,6 +54,9 @@ typedef enum {
|
|||
typedef enum {
|
||||
NP_DGRAM,
|
||||
NP_DTLS, //connected via ICE/WebRTC
|
||||
NP_KEXLAN, //layered over some silly lobby mess
|
||||
#define NP_ISLAYERED(np) (np>=NP_DTLS && np<=NP_KEXLAN)
|
||||
|
||||
NP_STREAM,
|
||||
NP_TLS,
|
||||
NP_WS,
|
||||
|
@ -166,6 +169,18 @@ enum addressscope_e
|
|||
};
|
||||
enum addressscope_e NET_ClassifyAddress(netadr_t *adr, const char **outdesc);
|
||||
|
||||
struct urischeme_s
|
||||
{
|
||||
const char *name;
|
||||
netproto_t prot; //NP_INVALID means its a game-specific one that should really be handled elsewhere but is silently ignored by the netcode.
|
||||
netadrtype_t family; //usually NA_INVALID, unless ipv4/ipv6-specific
|
||||
enum
|
||||
{
|
||||
URISCHEME_NEEDSRESOURCE = (1<<0), //forwards it on to the server
|
||||
} flags;
|
||||
};
|
||||
const struct urischeme_s *NET_IsURIScheme(const char *possible);
|
||||
|
||||
qboolean NET_AddrIsReliable(netadr_t *adr); //hints that the protocol is reliable. if so, we don't need to wait for acks
|
||||
qboolean NET_IsEncrypted(netadr_t *adr);
|
||||
qboolean NET_CompareAdr (netadr_t *a, netadr_t *b);
|
||||
|
@ -198,6 +213,9 @@ enum certprops_e
|
|||
QCERT_PEERCERTIFICATE, //should be the primary cert, ignoring chain. no fixed maximum size required, mostly 2k but probably best to allow at leasy 5k.. or 8k.
|
||||
|
||||
QCERT_LOCALCERTIFICATE, //the cert we're using/advertising. may have no context. to tell people what fp to expect.
|
||||
|
||||
QCERT_LOBBYSTATUS, //for special-case lobby wrappers.
|
||||
QCERT_LOBBYSENDCHAT, //to send chat via the stupid lobby instead of the game itself.
|
||||
};
|
||||
int NET_GetConnectionCertificate(struct ftenet_connections_s *col, netadr_t *a, enum certprops_e prop, char *out, size_t outsize);
|
||||
|
||||
|
|
|
@ -387,7 +387,10 @@ void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t *adr, int qport)
|
|||
|
||||
chan->qport = qport;
|
||||
|
||||
chan->qportsize = 2;
|
||||
if (adr->prot == NP_KEXLAN)
|
||||
chan->qportsize = 0;
|
||||
else
|
||||
chan->qportsize = 2;
|
||||
}
|
||||
|
||||
|
||||
|
@ -790,6 +793,28 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
send_reliable = true;
|
||||
}
|
||||
|
||||
if (send_reliable && chan->remote_address.prot == NP_KEXLAN)
|
||||
#ifndef SERVERONLY
|
||||
if (!cls.demoplayback)
|
||||
#endif
|
||||
{
|
||||
if (chan->reliable_length)
|
||||
{
|
||||
send.data = send_buf;
|
||||
send.maxsize = (chan->mtu?chan->mtu:MAX_QWMSGLEN) + PACKET_HEADER;
|
||||
send.cursize = 0;
|
||||
|
||||
MSG_WriteLong (&send, 1u<<31);
|
||||
MSG_WriteLong (&send, 1u<<31);
|
||||
SZ_Write (&send, chan->reliable_buf, chan->reliable_length);
|
||||
|
||||
if (NETERR_SENT == NET_SendPacket (chan->sock, send.cursize, send.data, &chan->remote_address))
|
||||
chan->reliable_length = 0; //the lower layer will handle any retransmission for us.
|
||||
}
|
||||
send_reliable = 0;
|
||||
chan->incoming_reliable_sequence = 0;
|
||||
}
|
||||
|
||||
// write the packet header
|
||||
send.data = send_buf;
|
||||
send.maxsize = (chan->mtu?chan->mtu:MAX_QWMSGLEN) + PACKET_HEADER;
|
||||
|
@ -950,6 +975,9 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
|
||||
if (e == NETERR_SENT)
|
||||
{
|
||||
if (send_reliable && NET_AddrIsReliable(&chan->remote_address))
|
||||
chan->reliable_length = 0; //we know the peer will receive it. don't worry about waiting for their acks.
|
||||
|
||||
chan->bytesout += send.cursize;
|
||||
Netchan_Block(chan, send.cursize, rate);
|
||||
}
|
||||
|
@ -1025,7 +1053,7 @@ qboolean Netchan_Process (netchan_t *chan)
|
|||
// skip over the qport if we are a server (its handled elsewhere)
|
||||
#ifndef CLIENTONLY
|
||||
if (chan->sock == NS_SERVER)
|
||||
MSG_ReadShort ();
|
||||
MSG_ReadSkip (chan->qportsize);
|
||||
#endif
|
||||
|
||||
if (chan->pext_fragmentation)
|
||||
|
@ -1083,7 +1111,8 @@ qboolean Netchan_Process (netchan_t *chan)
|
|||
//
|
||||
// discard stale or duplicated packets
|
||||
//
|
||||
if (sequence <= (unsigned)chan->incoming_sequence)
|
||||
if (sequence <= (unsigned)chan->incoming_sequence &&
|
||||
!(reliable_message && chan->remote_address.prot == NP_KEXLAN)) //*sigh* reliables don't work properly here.
|
||||
{
|
||||
if (showdrop.value)
|
||||
Con_TPrintf ("%s:Out of order packet %i at %i\n"
|
||||
|
@ -1180,11 +1209,16 @@ qboolean Netchan_Process (netchan_t *chan)
|
|||
//
|
||||
// if this message contains a reliable message, bump incoming_reliable_sequence
|
||||
//
|
||||
chan->incoming_sequence = sequence;
|
||||
chan->incoming_acknowledged = sequence_ack;
|
||||
chan->incoming_reliable_acknowledged = reliable_ack;
|
||||
if (reliable_message)
|
||||
chan->incoming_reliable_sequence ^= 1;
|
||||
if (reliable_message && chan->remote_address.prot == NP_KEXLAN) //*sigh* reliables don't work properly here.
|
||||
; //don't corrupt sequences/acks/etc.
|
||||
else
|
||||
{
|
||||
chan->incoming_sequence = sequence;
|
||||
chan->incoming_acknowledged = sequence_ack;
|
||||
chan->incoming_reliable_acknowledged = reliable_ack;
|
||||
if (reliable_message)
|
||||
chan->incoming_reliable_sequence ^= 1;
|
||||
}
|
||||
|
||||
//
|
||||
// the message can now be read from the current message pointer
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1943,7 +1943,7 @@ qboolean SV_ChallengePasses(int challenge)
|
|||
//this means that DP clients tend to connect as generic NQ clients.
|
||||
//and because DP _REQUIRES_ sv_bigcoords, they tend to end up being given fitz/rmq protocols
|
||||
//thus we don't respond to the connect if sv_listen_dp is 1, and we had a recent getchallenge request. recent is 2 secs.
|
||||
static qboolean SV_ChallengeRecent(void)
|
||||
qboolean SV_ChallengeRecent(void)
|
||||
{
|
||||
int curtime = realtime; //yeah, evil. sue me. consitent with challenges.
|
||||
int i;
|
||||
|
@ -3264,13 +3264,13 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
else //measure this guy in minuites.
|
||||
s = va(langtext("Welcome back %s. You have previously spent %i mins connected\n", newcl->language), newcl->name, (int)(rs.timeonserver/60));
|
||||
|
||||
SV_OutOfBandPrintf (info->protocol == SCP_QUAKE2, &info->adr, s);
|
||||
SV_OutOfBandPrintf (ISQ2CLIENT(info), &info->adr, s);
|
||||
}
|
||||
else if (!preserveparms)
|
||||
{
|
||||
SV_GetNewSpawnParms(newcl);
|
||||
|
||||
SV_OutOfBandTPrintf (info->protocol == SCP_QUAKE2, &info->adr, newcl->language, "Welcome %s. Your time on this server is being logged and ranked\n", newcl->name, (int)rs.timeonserver);
|
||||
SV_OutOfBandTPrintf (ISQ2CLIENT(info), &info->adr, newcl->language, "Welcome %s. Your time on this server is being logged and ranked\n", newcl->name, (int)rs.timeonserver);
|
||||
}
|
||||
//else loaded players already have their initial parms set
|
||||
}
|
||||
|
@ -3570,7 +3570,7 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
}*/
|
||||
|
||||
version = atoi(Cmd_Argv(1));
|
||||
if (version >= 31 && version <= 34)
|
||||
if (version >= PROTOCOL_VERSION_Q2_MIN && version <= PROTOCOL_VERSION_Q2)
|
||||
info.protocol = SCP_QUAKE2;
|
||||
#ifdef NQPROT
|
||||
else if (version == NQ_NETCHAN_VERSION)
|
||||
|
@ -3650,11 +3650,13 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
}
|
||||
}
|
||||
|
||||
// see if the challenge is valid.
|
||||
if (net_from.type == NA_LOOPBACK) //normal rules don't apply
|
||||
;
|
||||
else if (net_from.prot != NP_DGRAM)
|
||||
; //challenge checks are irrelevant when we've alread passed a challenge in a lower network layer.
|
||||
else
|
||||
{
|
||||
// see if the challenge is valid
|
||||
if (!SV_ChallengePasses(info.challenge))
|
||||
{
|
||||
if (sv_listen_dp.ival && !info.challenge && info.protocol == SCP_QUAKEWORLD)
|
||||
|
@ -4940,8 +4942,16 @@ void SV_ReadPacket(void)
|
|||
continue;
|
||||
#endif
|
||||
|
||||
if (cl->netchan.qport != qport)
|
||||
continue;
|
||||
if (cl->netchan.qportsize == 0)
|
||||
{ //no qports... use the actual port.
|
||||
if (cl->netchan.remote_address.port != net_from.port)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cl->netchan.qport != qport)
|
||||
continue;
|
||||
}
|
||||
if (cl->netchan.remote_address.port != net_from.port)
|
||||
{
|
||||
Con_DPrintf ("SV_ReadPackets: fixing up a translated port\n");
|
||||
|
@ -4994,7 +5004,7 @@ dominping:
|
|||
cl->send_message = true; // reply at end of frame
|
||||
|
||||
#ifdef Q2SERVER
|
||||
if (cl->protocol == SCP_QUAKE2)
|
||||
if (ISQ2CLIENT(cl))
|
||||
SVQ2_ExecuteClientMessage(cl);
|
||||
else
|
||||
#endif
|
||||
|
@ -5107,7 +5117,7 @@ qboolean SV_ReadPackets (float *delay)
|
|||
cl->send_message = true; // reply at end of frame
|
||||
|
||||
#ifdef Q2SERVER
|
||||
if (cl->protocol == SCP_QUAKE2)
|
||||
if (ISQ2CLIENT(cl))
|
||||
SVQ2_ExecuteClientMessage(cl);
|
||||
else
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue