From 6dca288eb9bac8251395386e6495866e05806f4e Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Fri, 1 Dec 2023 16:18:45 +1000 Subject: [PATCH] client: improve server connection status messages Always logs various errors and rejections that previously were only visible with developer cvar(s) set. Among other things this fixes silent failure when trying to join a full server. Includes IP address in more messages. Uses CON_ERROR and CON_WARN colours for various errors and warns. Moves status message generation to the code that sets the relevant states. This allows more information to be included, makes the code easier to follow and reduces polling. Fixes some cases where a message was always clobbered before it could be displayed. Merges the built-in menu and loading screen connection status generation and buffering. Simplifies challenge request retry counting. Signed-off-by: bones_was_here --- cl_main.c | 29 +++++++-------- cl_parse.c | 44 +++++++++++------------ cl_screen.c | 26 +++++++------- cl_screen.h | 2 ++ crypto.c | 20 ++++++++--- crypto.h | 4 +-- menu.c | 26 +++++--------- menu.h | 3 +- netconn.c | 100 +++++++++++++++++++++++----------------------------- 9 files changed, 118 insertions(+), 136 deletions(-) diff --git a/cl_main.c b/cl_main.c index 218f7b24..6b557283 100644 --- a/cl_main.c +++ b/cl_main.c @@ -447,10 +447,14 @@ void CL_DisconnectEx(qbool kicked, const char *fmt, ... ) NetConn_Close(cls.netcon); cls.netcon = NULL; - if(fmt) - Con_Printf("Disconnect: %s\n", reason); + + // It's possible for a server to disconnect a player with an empty reason + // which is checked here rather than above so we don't print "Disconnect by user". + if(fmt && reason[0] != '\0') + dpsnprintf(cl_connect_status, sizeof(cl_connect_status), "Disconnect: %s", reason); else - Con_Printf("Disconnected\n"); + strlcpy(cl_connect_status, "Disconnected", sizeof(cl_connect_status)); + Con_Printf("%s\n", cl_connect_status); } cls.state = ca_disconnected; cl.islocalgame = false; @@ -492,7 +496,7 @@ static void CL_Reconnect_f(cmd_state_t *cmd) if (temp[0]) CL_EstablishConnection(temp, -1); else - Con_Printf("Reconnect to what server? (you have not connected to a server yet)\n"); + Con_Printf(CON_WARN "Reconnect to what server? (you have not connected to a server yet)\n"); return; } // if connected, do something based on protocol @@ -572,18 +576,13 @@ void CL_EstablishConnection(const char *address, int firstarg) if (Sys_CheckParm("-benchmark")) return; - // clear menu's connect error message -#ifdef CONFIG_MENU - M_Update_Return_Reason(""); -#endif - // make sure the client ports are open before attempting to connect NetConn_UpdateSockets(); if (LHNETADDRESS_FromString(&cls.connect_address, address, 26000) && (cls.connect_mysocket = NetConn_ChooseClientSocketForAddress(&cls.connect_address))) { cls.connect_trying = true; - cls.connect_remainingtries = 3; + cls.connect_remainingtries = 10; cls.connect_nextsendtime = 0; // only NOW, set connect_userinfo @@ -601,17 +600,13 @@ void CL_EstablishConnection(const char *address, int firstarg) *cls.connect_userinfo = 0; } -#ifdef CONFIG_MENU - M_Update_Return_Reason("Trying to connect..."); -#endif + strlcpy(cl_connect_status, "Connect: pending...", sizeof(cl_connect_status)); SCR_BeginLoadingPlaque(false); } else { - Con_Print("Unable to find a suitable network socket to connect to server.\n"); -#ifdef CONFIG_MENU - M_Update_Return_Reason("No network"); -#endif + Con_Printf(CON_ERROR "Connect: failed, unable to find a network socket suitable to reach %s\n", address); + strlcpy(cl_connect_status, "Connect: failed, no network", sizeof(cl_connect_status)); } } diff --git a/cl_parse.c b/cl_parse.c index 374b6ed6..ae96302b 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -199,6 +199,13 @@ static void QW_CL_NextUpload_f(cmd_state_t *cmd); //static qbool QW_CL_IsUploading(void); static void QW_CL_StopUpload_f(cmd_state_t *cmd); +static inline void CL_SetSignonStage_WithMsg(int signon_stage) +{ + cls.signon = signon_stage; + dpsnprintf(cl_connect_status, sizeof(cl_connect_status), "Connect: signon stage %i of %i", cls.signon, SIGNONS); + Con_DPrint(cl_connect_status); +} + /* ================== CL_ParseStartSoundPacket @@ -614,7 +621,7 @@ static void QW_CL_RequestNextDownload(void) // if we're still in signon stages, request the next one if (cls.signon != SIGNONS) { - cls.signon = SIGNONS-1; + CL_SetSignonStage_WithMsg(SIGNONS - 1); // we'll go to SIGNONS when the first entity update is received MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "begin %i", cl.qw_servercount)); @@ -842,7 +849,7 @@ static void QW_CL_ParseModelList(void) return; } - cls.signon = 2; + CL_SetSignonStage_WithMsg(2); cls.qw_downloadnumber = 0; cls.qw_downloadtype = dl_model; QW_CL_RequestNextDownload(); @@ -878,7 +885,7 @@ static void QW_CL_ParseSoundList(void) return; } - cls.signon = 2; + CL_SetSignonStage_WithMsg(2); cls.qw_downloadnumber = 0; cls.qw_downloadtype = dl_sound; QW_CL_RequestNextDownload(); @@ -898,7 +905,7 @@ static void QW_CL_Changing_f(cmd_state_t *cmd) S_StopAllSounds(); cl.intermission = 0; - cls.signon = 1; // not active anymore, but not disconnected + CL_SetSignonStage_WithMsg(1); // not active anymore, but not disconnected Con_Printf("\nChanging map...\n"); } @@ -1602,8 +1609,10 @@ CL_SignonReply An svc_signonnum has been received, perform a client side setup ===================== */ -static void CL_SignonReply (void) +static void CL_SignonReply(int signon_stage) { + CL_SetSignonStage_WithMsg(signon_stage); + Con_DPrintf("CL_SignonReply: %i\n", cls.signon); switch (cls.signon) @@ -1787,7 +1796,7 @@ static void CL_ParseServerInfo (void) cl.loadfinished = false; cls.state = ca_connected; - cls.signon = 1; + CL_SetSignonStage_WithMsg(1); // note: on QW protocol we can't set up the gameworld until after // downloads finish... @@ -3773,20 +3782,14 @@ void CL_ParseServerMessage(void) EntityFrameQW_CL_ReadFrame(false); // first update is the final signon stage if (cls.signon == SIGNONS - 1) - { - cls.signon = SIGNONS; - CL_SignonReply (); - } + CL_SignonReply(SIGNONS); break; case qw_svc_deltapacketentities: EntityFrameQW_CL_ReadFrame(true); // first update is the final signon stage if (cls.signon == SIGNONS - 1) - { - cls.signon = SIGNONS; - CL_SignonReply (); - } + CL_SignonReply(SIGNONS); break; case qw_svc_maxspeed: @@ -3846,11 +3849,8 @@ void CL_ParseServerMessage(void) cmdlogname[cmdindex] = temp; SHOWNET("fast update"); if (cls.signon == SIGNONS - 1) - { // first update is the final signon stage - cls.signon = SIGNONS; - CL_SignonReply (); - } + CL_SignonReply(SIGNONS); EntityFrameQuake_ReadEntity (cmd&127); continue; } @@ -4141,8 +4141,7 @@ void CL_ParseServerMessage(void) // reconnect somehow, so allow signon 1 even if at signon 1 if (i <= cls.signon && i != 1) Host_Error ("Received signon %i when at %i", i, cls.signon); - cls.signon = i; - CL_SignonReply (); + CL_SignonReply(i); break; case svc_killedmonster: @@ -4246,11 +4245,8 @@ void CL_ParseServerMessage(void) break; case svc_entities: if (cls.signon == SIGNONS - 1) - { // first update is the final signon stage - cls.signon = SIGNONS; - CL_SignonReply (); - } + CL_SignonReply(SIGNONS); if (cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3) EntityFrame_CL_ReadFrame(); else if (cls.protocol == PROTOCOL_DARKPLACES4) diff --git a/cl_screen.c b/cl_screen.c index 6e9fbeb6..a313e1e3 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -1558,6 +1558,9 @@ rtexture_t *loadingscreentexture = NULL; // last framebuffer before loading scre static float loadingscreentexture_vertex3f[12]; static float loadingscreentexture_texcoord2f[8]; static int loadingscreenpic_number = 0; +/// User-friendly connection status for the menu and/or loading screen, +/// colours and \n not supported. +char cl_connect_status[MAX_QPATH]; // should match size of loadingscreenstack_t msg[] static void SCR_DrawLoadingScreen(void); static void SCR_DrawScreen (void) @@ -1729,24 +1732,19 @@ static void SCR_DrawScreen (void) if (scr_loading) { - loadingscreenstack_t connect_status; - qbool show_connect_status = !loadingscreenstack && (cls.connect_trying || cls.state == ca_connected); - if (show_connect_status) + // connect_status replaces any dummy_status + if ((!loadingscreenstack || loadingscreenstack->msg[0] == '\0') && cl_connect_status[0] != '\0') { + loadingscreenstack_t connect_status, *og_ptr = loadingscreenstack; + connect_status.absolute_loading_amount_min = 0; - if (cls.signon > 0) - dpsnprintf(connect_status.msg, sizeof(connect_status.msg), "Connect: Signon stage %i of %i", cls.signon, SIGNONS); - else if (cls.connect_remainingtries > 0) - dpsnprintf(connect_status.msg, sizeof(connect_status.msg), "Connect: Trying... %i", cls.connect_remainingtries); - else - dpsnprintf(connect_status.msg, sizeof(connect_status.msg), "Connect: Waiting %i seconds for reply", 10 + cls.connect_remainingtries); + strlcpy(connect_status.msg, cl_connect_status, sizeof(cl_connect_status)); loadingscreenstack = &connect_status; + SCR_DrawLoadingScreen(); + loadingscreenstack = og_ptr; } - - SCR_DrawLoadingScreen(); - - if (show_connect_status) - loadingscreenstack = NULL; + else + SCR_DrawLoadingScreen(); } SCR_DrawConsole(); diff --git a/cl_screen.h b/cl_screen.h index aef5a234..57cfd282 100644 --- a/cl_screen.h +++ b/cl_screen.h @@ -17,6 +17,8 @@ extern struct cvar_s scr_screenshot_png; extern struct cvar_s scr_screenshot_gammaboost; extern struct cvar_s scr_screenshot_name; +extern char cl_connect_status[MAX_QPATH]; + void CL_Screen_NewMap(void); void CL_Screen_Init(void); void CL_Screen_Shutdown(void); diff --git a/crypto.c b/crypto.c index 21b70954..d910e491 100644 --- a/crypto.c +++ b/crypto.c @@ -1141,11 +1141,11 @@ static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned ch { if(length_received >= 5 && Crypto_LittleLong((const char *) buffer) == FOURCC_D0ER) { - Con_Printf("Error response from keygen server: %.*s\n", (int)(length_received - 5), buffer + 5); + Con_Printf(CON_ERROR "Error response from keygen server: %.*s\n", (int)(length_received - 5), buffer + 5); } else { - Con_Printf("Invalid response from keygen server:\n"); + Con_Printf(CON_ERROR "Invalid response from keygen server:\n"); Com_HexDumpToConsole(buffer, (int)length_received); } keygen_i = -1; @@ -2106,7 +2106,7 @@ static int Crypto_SoftClientError(char *data_out, size_t *len_out, const char *m return CRYPTO_DISCARD; } -int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress) +int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress, const char *peeraddressstring) { crypto_t *crypto = &cls.crypto; const char *string = data_in; @@ -2214,7 +2214,12 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, // Must check the source IP here, if we want to prevent other servers' replies from falsely advancing the crypto state, preventing successful connect to the real server. if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) - return Crypto_SoftClientError(data_out, len_out, "challenge message from wrong server"); + { + char warn_msg[128]; + + dpsnprintf(warn_msg, sizeof(warn_msg), "ignoring challenge message from wrong server %s", peeraddressstring); + return Crypto_SoftClientError(data_out, len_out, warn_msg); + } // if we have a stored host key for the server, assume serverid to already be selected! // (the loop will refuse to overwrite this one then) @@ -2422,7 +2427,12 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, // Must check the source IP here, if we want to prevent other servers' replies from falsely advancing the crypto state, preventing successful connect to the real server. if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) - return Crypto_SoftClientError(data_out, len_out, "d0pk\\ message from wrong server"); + { + char warn_msg[128]; + + dpsnprintf(warn_msg, sizeof(warn_msg), "ignoring d0pk\\ message from wrong server %s", peeraddressstring); + return Crypto_SoftClientError(data_out, len_out, warn_msg); + } cnt = InfoString_GetValue(string + 4, "id", infostringvalue, sizeof(infostringvalue)); id = (cnt ? atoi(cnt) : -1); diff --git a/crypto.h b/crypto.h index 306134de..bbb4ea1f 100644 --- a/crypto.h +++ b/crypto.h @@ -65,8 +65,8 @@ const void *Crypto_DecryptPacket(crypto_t *crypto, const void *data_src, size_t #define CRYPTO_MATCH 1 // process as usual (packet was used) #define CRYPTO_DISCARD 2 // discard this packet #define CRYPTO_REPLACE 3 // make the buffer the current packet -int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, struct lhnetaddress_s *peeraddress); -int Crypto_ServerParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, struct lhnetaddress_s *peeraddress); +int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress, const char *peeraddressstring); +int Crypto_ServerParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress); // if len_out is nonzero, the packet is to be sent to the client diff --git a/menu.c b/menu.c index f2745353..6749f6da 100644 --- a/menu.c +++ b/menu.c @@ -34,7 +34,6 @@ static cvar_t menu_progs = {CF_CLIENT, "menu_progs", "menu.dat", "name of quakec static int NehGameType; enum m_state_e m_state; -char m_return_reason[128]; void M_Menu_Main_f(cmd_state_t *cmd); void M_Menu_SinglePlayer_f(cmd_state_t *cmd); @@ -108,13 +107,6 @@ static void M_ModList_Key(cmd_state_t *cmd, int key, int ascii); static qbool m_entersound; ///< play after drawing a frame, so caching won't disrupt the sound -void M_Update_Return_Reason(const char *s) -{ - strlcpy(m_return_reason, s, sizeof(m_return_reason)); - if (s) - Con_DPrintf("%s\n", s); -} - #define StartingGame (m_multiplayer_cursor == 1) #define JoiningGame (m_multiplayer_cursor == 0) @@ -3344,7 +3336,7 @@ void M_Menu_LanConfig_f(cmd_state_t *cmd) lanConfig_port = 26000; dpsnprintf(lanConfig_portname, sizeof(lanConfig_portname), "%u", (unsigned int) lanConfig_port); - M_Update_Return_Reason(""); + cl_connect_status[0] = '\0'; } @@ -3397,8 +3389,8 @@ static void M_LanConfig_Draw (void) if (lanConfig_cursor == 3) M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [lanConfig_cursor], 10+((int)(host.realtime*4)&1)); - if (*m_return_reason) - M_Print(basex, 168, m_return_reason); + if (*cl_connect_status) + M_Print(basex, 168, cl_connect_status); } @@ -4394,7 +4386,7 @@ void M_Menu_ServerList_f(cmd_state_t *cmd) m_state = m_slist; m_entersound = true; slist_cursor = 0; - M_Update_Return_Reason(""); + cl_connect_status[0] = '\0'; if (lanConfig_cursor == 2) Net_SlistQW_f(cmd); else @@ -4418,8 +4410,8 @@ static void M_ServerList_Draw (void) ServerList_GetPlayerStatistics(&statnumplayers, &statmaxplayers); s = va(vabuf, sizeof(vabuf), "%u/%u masters %u/%u servers %u/%u players", masterreplycount, masterquerycount, serverreplycount, serverquerycount, statnumplayers, statmaxplayers); M_PrintRed((640 - strlen(s) * 8) / 2, 32, s); - if (*m_return_reason) - M_Print(16, menu_height - 8, m_return_reason); + if (*cl_connect_status) + M_Print(16, menu_height - 8, cl_connect_status); y = 48; slist_visible = (menu_height - 16 - y) / 8 / 2; start = min(slist_cursor - min(slist_cursor, slist_visible >> 1), serverlist_viewcount - min(serverlist_viewcount, slist_visible)); @@ -4617,7 +4609,7 @@ void M_Menu_ModList_f(cmd_state_t *cmd) m_state = m_modlist; m_entersound = true; modlist_cursor = 0; - M_Update_Return_Reason(""); + cl_connect_status[0] = '\0'; ModList_RebuildList(); } @@ -4667,8 +4659,8 @@ static void M_ModList_Draw (void) for (y = 0; y < modlist_numenabled; y++) M_PrintRed(432, 48 + y * 8, modlist[modlist_enabled[y]].dir); - if (*m_return_reason) - M_Print(16, menu_height - 8, m_return_reason); + if (*cl_connect_status) + M_Print(16, menu_height - 8, cl_connect_status); // scroll the list as the cursor moves y = 48; visible = (int)((menu_height - 16 - y) / 8 / 2); diff --git a/menu.h b/menu.h index 38a034f6..6dd0b37c 100644 --- a/menu.h +++ b/menu.h @@ -52,8 +52,7 @@ enum m_state_e { }; extern enum m_state_e m_state; -extern char m_return_reason[128]; -void M_Update_Return_Reason(const char *s); + /* // hard-coded menus diff --git a/netconn.c b/netconn.c index cb2992ea..bcc5f66e 100644 --- a/netconn.c +++ b/netconn.c @@ -1632,15 +1632,14 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, protocolversion_t initialprotocol) { crypto_t *crypto; + cls.connect_trying = false; -#ifdef CONFIG_MENU - M_Update_Return_Reason(""); -#endif // Disconnect from the current server or stop demo playback if(cls.state == ca_connected || cls.demoplayback) CL_Disconnect(); // allocate a net connection to keep track of things cls.netcon = NetConn_Open(mysocket, peeraddress); + strlcpy(cl_connect_status, "Connection established", sizeof(cl_connect_status)); crypto = &cls.netcon->crypto; if(cls.crypto.authenticated) { @@ -1656,7 +1655,9 @@ static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_ crypto_keyfp_recommended_length, crypto->client_keyfp[0] ? crypto->client_keyfp : "-" ); } - Con_Printf("Connection accepted to %s\n", cls.netcon->address); + else + Con_Printf("%s to %s\n", cl_connect_status, cls.netcon->address); + key_dest = key_game; #ifdef CONFIG_MENU m_state = m_none; @@ -2038,7 +2039,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat } sendlength = sizeof(senddata) - 4; - switch(Crypto_ClientParsePacket(string, length, senddata+4, &sendlength, peeraddress)) + switch(Crypto_ClientParsePacket(string, length, senddata+4, &sendlength, peeraddress, addressstring2)) { case CRYPTO_NOMATCH: // nothing to do @@ -2119,15 +2120,15 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat { // darkplaces or quake3 char protocolnames[1400]; - Con_DPrintf("\"%s\" received, sending connect request back to %s\n", string, addressstring2); + if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) { - Con_DPrintf("challenge message from wrong server %s\n", addressstring2); + Con_Printf(CON_WARN "ignoring challenge message from wrong server %s\n", addressstring2); return true; } + Con_DPrintf("\"%s\" received, sending connect request back to %s\n", string, addressstring2); + strlcpy(cl_connect_status, "Connect: replying to challenge...", sizeof(cl_connect_status)); + Protocol_Names(protocolnames, sizeof(protocolnames)); -#ifdef CONFIG_MENU - M_Update_Return_Reason("Got challenge response"); -#endif // 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); // TODO: add userinfo stuff here instead of using NQ commands? @@ -2140,30 +2141,23 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat { // darkplaces or quake3 if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) { - Con_DPrintf("accept message from wrong server %s\n", addressstring2); + Con_Printf(CON_WARN "ignoring accept message from wrong server %s\n", addressstring2); return true; } -#ifdef CONFIG_MENU - M_Update_Return_Reason("Accepted"); -#endif NetConn_ConnectionEstablished(mysocket, peeraddress, PROTOCOL_DARKPLACES3); return true; } if (length > 7 && !memcmp(string, "reject ", 7) && cls.connect_trying) { - char rejectreason[128]; if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) { - Con_DPrintf("reject message from wrong server %s\n", addressstring2); + Con_Printf(CON_WARN "ignoring reject message from wrong server %s\n", addressstring2); return true; } cls.connect_trying = false; string += 7; - length = min(length - 7, (int)sizeof(rejectreason) - 1); - memcpy(rejectreason, string, length); - rejectreason[length] = 0; -#ifdef CONFIG_MENU - M_Update_Return_Reason(rejectreason); -#endif + length = min(length - 7, (int)sizeof(cl_connect_status) - 1); + dpsnprintf(cl_connect_status, sizeof(cl_connect_status), "Connect: rejected, %.*s", length, string); + Con_Printf(CON_ERROR "Connect: rejected by %s\n" CON_ERROR "%.*s\n", addressstring2, length, string); return true; } #ifdef CONFIG_MENU @@ -2315,13 +2309,12 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat { // challenge message if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) { - Con_DPrintf("c message from wrong server %s\n", addressstring2); + Con_Printf(CON_WARN "ignoring c message from wrong server %s\n", addressstring2); return true; } - Con_Printf("challenge %s received, sending QuakeWorld connect request back to %s\n", string + 1, addressstring2); -#ifdef CONFIG_MENU - M_Update_Return_Reason("Got QuakeWorld challenge response"); -#endif + Con_DPrintf("challenge %s received, sending QuakeWorld connect request back to %s\n", string + 1, addressstring2); + strlcpy(cl_connect_status, "Connect: replying to challenge...", sizeof(cl_connect_status)); + cls.qw_qport = qport.integer; // 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); @@ -2334,12 +2327,9 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat { // accept message if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) { - Con_DPrintf("j message from wrong server %s\n", addressstring2); + Con_Printf(CON_WARN "ignoring j message from wrong server %s\n", addressstring2); return true; } -#ifdef CONFIG_MENU - M_Update_Return_Reason("QuakeWorld Accepted"); -#endif NetConn_ConnectionEstablished(mysocket, peeraddress, PROTOCOL_QUAKEWORLD); return true; } @@ -2396,7 +2386,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat { // qw print command, used by rcon replies too if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address) && LHNETADDRESS_Compare(peeraddress, &cls.rcon_address)) { - Con_DPrintf("n message from wrong server %s\n", addressstring2); + Con_Printf(CON_WARN "ignoring n message from wrong server %s\n", addressstring2); return true; } Con_Printf("QW print command from server at %s:\n%s\n", addressstring2, string + 1); @@ -2435,7 +2425,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat { lhnetaddress_t clientportaddress; if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) { - Con_DPrintf("CCREP_ACCEPT message from wrong server %s\n", addressstring2); + Con_Printf(CON_WARN "ignoring CCREP_ACCEPT message from wrong server %s\n", addressstring2); break; } clientportaddress = *peeraddress; @@ -2457,23 +2447,18 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat Con_Printf("Connected to ProQuake %.1f server, enabling precise aim\n", cls.proquake_serverversion / 10.0f); // 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); -#ifdef CONFIG_MENU - M_Update_Return_Reason("Accepted"); -#endif NetConn_ConnectionEstablished(mysocket, &clientportaddress, PROTOCOL_QUAKE); } break; case CCREP_REJECT: - if (developer_extra.integer) { - Con_DPrintf("CCREP_REJECT message from wrong server %s\n", addressstring2); - break; - } if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) + { + Con_Printf(CON_WARN "ignoring CCREP_REJECT message from wrong server %s\n", addressstring2); break; + } cls.connect_trying = false; -#ifdef CONFIG_MENU - M_Update_Return_Reason((char *)MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); -#endif + dpsnprintf(cl_connect_status, sizeof(cl_connect_status), "Connect: rejected, %s", MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); + Con_Printf(CON_ERROR "Connect: rejected by %s\n%s\n", addressstring2, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); break; case CCREP_SERVER_INFO: if (developer_extra.integer) @@ -2501,7 +2486,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat break; case CCREP_RCON: // RocketGuy: ProQuake rcon support if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.rcon_address)) { - Con_DPrintf("CCREP_RCON message from wrong server %s\n", addressstring2); + Con_Printf(CON_WARN "ignoring CCREP_RCON message from wrong server %s\n", addressstring2); break; } if (developer_extra.integer) @@ -2653,22 +2638,26 @@ void NetConn_ClientFrame(void) unsigned char readbuffer[NET_HEADERSIZE+NET_MAXMESSAGE]; NetConn_UpdateSockets(); + if (cls.connect_trying && cls.connect_nextsendtime < host.realtime) { -#ifdef CONFIG_MENU - if (cls.connect_remainingtries == 0) - M_Update_Return_Reason("Connect: Waiting 10 seconds for reply"); -#endif - cls.connect_nextsendtime = host.realtime + 1; - cls.connect_remainingtries--; - if (cls.connect_remainingtries <= -10) + if (cls.connect_remainingtries > 0) { + cls.connect_remainingtries--; + dpsnprintf(cl_connect_status, sizeof(cl_connect_status), "Connect: sending initial request, %i %s left...", cls.connect_remainingtries, cls.connect_remainingtries == 1 ? "retry" : "retries"); + } + else + { + char address[128]; + cls.connect_trying = false; -#ifdef CONFIG_MENU - M_Update_Return_Reason("Connect: Failed"); -#endif + LHNETADDRESS_ToString(&cls.connect_address, address, sizeof(address), true); + strlcpy(cl_connect_status, "Connect: failed, no reply", sizeof(cl_connect_status)); + Con_Printf(CON_ERROR "%s from %s\n", cl_connect_status, address); return; } + cls.connect_nextsendtime = host.realtime + 1; + // try challenge first (newer DP server or QW) NetConn_WriteString(cls.connect_mysocket, "\377\377\377\377getchallenge", &cls.connect_address); // then try netquake as a fallback (old server, or netquake) @@ -2691,6 +2680,7 @@ void NetConn_ClientFrame(void) NetConn_Write(cls.connect_mysocket, cl_message.data, cl_message.cursize, &cls.connect_address); SZ_Clear(&cl_message); } + for (i = 0;i < cl_numsockets;i++) { while (cl_sockets[i] && (length = NetConn_Read(cl_sockets[i], readbuffer, sizeof(readbuffer), &peeraddress)) > 0) @@ -3939,7 +3929,7 @@ void NetConn_QueryMasters(qbool querydp, qbool queryqw) if (!masterquerycount) { Con_Print(CON_ERROR "Unable to query master servers, no suitable network sockets active.\n"); - M_Update_Return_Reason("No network"); + strlcpy(cl_connect_status, "No network", sizeof(cl_connect_status)); } } #endif -- 2.39.2