Commit 7ebde22b by James R.

Make mod update, room list and server list multithreaded

This took fucking ages and it still fails sometimes in edge cases, but I don't give a FUCK right now.
parent 886bd34b
......@@ -1801,8 +1801,92 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node)
M_SortServerList();
}
#ifdef HAVE_THREADS
struct Fetch_servers_ctx
{
int room;
int id;
};
static void
Fetch_servers_thread (struct Fetch_servers_ctx *ctx)
{
msg_server_t *server_list;
server_list = GetShortServersList(ctx->room, ctx->id);
if (server_list)
{
I_lock_mutex(&ms_QueryId_mutex);
{
if (ctx->id != ms_QueryId)
{
free(server_list);
server_list = NULL;
}
}
I_unlock_mutex(ms_QueryId_mutex);
if (server_list)
{
I_lock_mutex(&m_menu_mutex);
{
if (m_waiting_mode == M_WAITING_SERVERS)
m_waiting_mode = M_NOT_WAITING;
}
I_unlock_mutex(m_menu_mutex);
I_lock_mutex(&ms_ServerList_mutex);
{
ms_ServerList = server_list;
}
I_unlock_mutex(ms_ServerList_mutex);
}
}
free(ctx);
}
#endif/*HAVE_THREADS*/
void CL_QueryServerList (msg_server_t *server_list)
{
INT32 i;
for (i = 0; server_list[i].header.buffer[0]; i++)
{
// Make sure MS version matches our own, to
// thwart nefarious servers who lie to the MS.
/* lol bruh, that version COMES from the servers */
//if (strcmp(version, server_list[i].version) == 0)
{
INT32 node = I_NetMakeNodewPort(server_list[i].ip, server_list[i].port);
if (node == -1)
break; // no more node free
SendAskInfo(node);
// Force close the connection so that servers can't eat
// up nodes forever if we never get a reply back from them
// (usually when they've not forwarded their ports).
//
// Don't worry, we'll get in contact with the working
// servers again when they send SERVERINFO to us later!
//
// (Note: as a side effect this probably means every
// server in the list will probably be using the same node (e.g. node 1),
// not that it matters which nodes they use when
// the connections are closed afterwards anyway)
// -- Monster Iestyn 12/11/18
Net_CloseConnection(node|FORCECLOSE);
}
}
}
void CL_UpdateServerList(boolean internetsearch, INT32 room)
{
#ifdef HAVE_THREADS
struct Fetch_servers_ctx *ctx;
#endif
SL_ClearServerList(0);
if (!netgame && I_NetOpenSocket)
......@@ -1820,53 +1904,32 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
if (internetsearch)
{
const msg_server_t *server_list;
INT32 i = -1;
server_list = GetShortServersList(room);
if (server_list)
{
char version[8] = "";
#if VERSION > 0 || SUBVERSION > 0
snprintf(version, sizeof (version), "%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION);
#else
strcpy(version, GetRevisionString());
#endif
version[sizeof (version) - 1] = '\0';
#ifdef HAVE_THREADS
ctx = malloc(sizeof *ctx);
for (i = 0; server_list[i].header.buffer[0]; i++)
{
// Make sure MS version matches our own, to
// thwart nefarious servers who lie to the MS.
/* This called from M_Refresh so I don't use a mutex */
m_waiting_mode = M_WAITING_SERVERS;
/* lol bruh, that version COMES from the servers */
//if (strcmp(version, server_list[i].version) == 0)
{
INT32 node = I_NetMakeNodewPort(server_list[i].ip, server_list[i].port);
if (node == -1)
break; // no more node free
SendAskInfo(node);
// Force close the connection so that servers can't eat
// up nodes forever if we never get a reply back from them
// (usually when they've not forwarded their ports).
//
// Don't worry, we'll get in contact with the working
// servers again when they send SERVERINFO to us later!
//
// (Note: as a side effect this probably means every
// server in the list will probably be using the same node (e.g. node 1),
// not that it matters which nodes they use when
// the connections are closed afterwards anyway)
// -- Monster Iestyn 12/11/18
Net_CloseConnection(node|FORCECLOSE);
}
}
I_lock_mutex(&ms_QueryId_mutex);
{
ctx->id = ms_QueryId;
}
I_unlock_mutex(ms_QueryId_mutex);
ctx->room = room;
//no server list?(-1) or no servers?(0)
if (!i)
I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx);
#else
msg_server_t *server_list;
server_list = GetShortServersList(room, 0);
if (server_list)
{
; /// TODO: display error or warning?
CL_QueryServerList(server_list);
free(server_list);
}
#endif
}
}
......@@ -5054,7 +5117,13 @@ void NetUpdate(void)
if (nowtime > resptime)
{
resptime = nowtime;
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Ticker();
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
CON_Ticker();
}
......
......@@ -18,6 +18,7 @@
#include "d_net.h"
#include "tables.h"
#include "d_player.h"
#include "mserv.h"
/*
The 'packet version' is used to distinguish packet formats.
......@@ -541,6 +542,7 @@ void CL_AddSplitscreenPlayer(void);
void CL_RemoveSplitscreenPlayer(void);
void CL_Reset(void);
void CL_ClearPlayer(INT32 playernum);
void CL_QueryServerList(msg_server_t *list);
void CL_UpdateServerList(boolean internetsearch, INT32 room);
// Is there a game running
boolean Playing(void);
......
......@@ -46,6 +46,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "hu_stuff.h"
#include "i_sound.h"
#include "i_system.h"
#include "i_threads.h"
#include "i_video.h"
#include "m_argv.h"
#include "m_menu.h"
......@@ -174,6 +175,8 @@ void D_ProcessEvents(void)
{
event_t *ev;
boolean eaten;
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
{
ev = &events[eventtail];
......@@ -189,7 +192,17 @@ void D_ProcessEvents(void)
}
// Menu input
if (M_Responder(ev))
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
{
eaten = M_Responder(ev);
}
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
if (eaten)
continue; // menu ate the event
// console input
......@@ -510,7 +523,13 @@ static void D_Display(void)
// vid size change is now finished if it was on...
vid.recalc = 0;
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of everything
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
// focus lost moved to M_Drawer
CON_Drawer();
......
......@@ -25,6 +25,7 @@
#include "w_wad.h"
#include "z_zone.h"
#include "i_system.h"
#include "i_threads.h"
#include "m_menu.h"
#include "dehacked.h"
#include "g_input.h"
......@@ -959,7 +960,13 @@ void F_IntroDrawer(void)
I_OsPolling();
I_UpdateNoBlit();
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of wipes
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
if (moviemode) // make sure we save frames for the white hold too
......
......@@ -25,6 +25,7 @@
#include "z_zone.h"
#include "i_system.h"
#include "i_threads.h"
#include "m_menu.h"
#include "console.h"
#include "d_main.h"
......@@ -589,7 +590,15 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
I_UpdateNoBlit();
if (drawMenu)
{
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of wipes
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
}
I_FinishUpdate(); // page flip or blit buffer
......
......@@ -19,6 +19,7 @@ Documentation available here.
#include "doomdef.h"
#include "d_clisrv.h"
#include "command.h"
#include "m_menu.h"
#include "mserv.h"
#include "i_tcp.h"/* for current_port */
#include "z_zone.h"
......@@ -193,11 +194,13 @@ HMS_end (struct HMS_buffer *buffer)
}
int
HMS_fetch_rooms (int joining)
HMS_fetch_rooms (int joining, int query_id)
{
struct HMS_buffer *hms;
int ok;
int doing_shit;
char *id;
char *title;
char *room_motd;
......@@ -209,6 +212,8 @@ HMS_fetch_rooms (int joining)
int i;
(void)query_id;
hms = HMS_connect("rooms");
if (! hms)
......@@ -216,6 +221,8 @@ HMS_fetch_rooms (int joining)
if (HMS_do(hms))
{
doing_shit = 1;
p = hms->buffer;
for (i = 0; i < NUM_LIST_ROOMS && ( end = strstr(p, "\n\n\n") );)
......@@ -236,6 +243,18 @@ HMS_fetch_rooms (int joining)
*/
if (joining || id_no != 0)
{
#ifdef HAVE_THREADS
I_lock_mutex(&ms_QueryId_mutex);
{
if (query_id != ms_QueryId)
doing_shit = 0;
}
I_unlock_mutex(ms_QueryId_mutex);
if (! doing_shit)
break;
#endif
room_list[i].header.buffer[0] = 1;
room_list[i].id = id_no;
......@@ -251,9 +270,31 @@ HMS_fetch_rooms (int joining)
break;
}
room_list[i].header.buffer[0] = 0;
if (doing_shit)
room_list[i].header.buffer[0] = 0;
ok = 1;
if (doing_shit)
{
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
{
for (i = 0; room_list[i].header.buffer[0]; i++)
{
if(*room_list[i].name != '\0')
{
MP_RoomMenu[i+1].text = room_list[i].name;
roomIds[i] = room_list[i].id;
MP_RoomMenu[i+1].status = IT_STRING|IT_CALL;
}
}
}
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
}
}
else
ok = 0;
......@@ -385,10 +426,12 @@ HMS_list_servers (void)
}
msg_server_t *
HMS_fetch_servers (msg_server_t *list, int room_number)
HMS_fetch_servers (msg_server_t *list, int room_number, int query_id)
{
struct HMS_buffer *hms;
int doing_shit;
char local_version[9];
char *room;
......@@ -404,6 +447,8 @@ HMS_fetch_servers (msg_server_t *list, int room_number)
int i;
(void)query_id;
if (room_number > 0)
{
hms = HMS_connect("rooms/%d/servers", room_number);
......@@ -416,6 +461,8 @@ HMS_fetch_servers (msg_server_t *list, int room_number)
if (HMS_do(hms))
{
doing_shit = 1;
snprintf(local_version, sizeof local_version,
"%d.%d.%d",
VERSION/100,
......@@ -448,6 +495,18 @@ HMS_fetch_servers (msg_server_t *list, int room_number)
if (address && port && title && version)
{
#ifdef HAVE_THREADS
I_lock_mutex(&ms_QueryId_mutex);
{
if (query_id != ms_QueryId)
doing_shit = 0;
}
I_unlock_mutex(ms_QueryId_mutex);
if (! doing_shit)
break;
#endif
if (strcmp(version, local_version) == 0)
{
strlcpy(list[i].ip, address, sizeof list[i].ip);
......@@ -474,11 +533,15 @@ HMS_fetch_servers (msg_server_t *list, int room_number)
}
}
if (! doing_shit)
break;
p = ( section_end + 2 );
}
while (section_end) ;
list[i].header.buffer[0] = 0;
if (doing_shit)
list[i].header.buffer[0] = 0;
}
else
list = NULL;
......
......@@ -32,6 +32,7 @@
#include "sounds.h"
#include "s_sound.h"
#include "i_system.h"
#include "i_threads.h"
// Addfile
#include "filesrch.h"
......@@ -121,6 +122,12 @@ typedef enum
NUM_QUITMESSAGES
} text_enum;
#ifdef HAVE_THREADS
I_mutex m_menu_mutex;
#endif
M_waiting_mode_t m_waiting_mode = M_NOT_WAITING;
const char *quitmsg[NUM_QUITMESSAGES];
// Stuff for customizing the player select screen Tails 09-22-2003
......@@ -996,7 +1003,7 @@ enum
FIRSTSERVERLINE
};
static menuitem_t MP_RoomMenu[] =
menuitem_t MP_RoomMenu[] =
{
{IT_STRING | IT_CALL, NULL, "<Unlisted Mode>", M_ChooseRoom, 9},
{IT_DISABLED, NULL, "", M_ChooseRoom, 18},
......@@ -3769,6 +3776,30 @@ void M_SetupNextMenu(menu_t *menudef)
{
INT16 i;
#ifdef HAVE_THREADS
if (currentMenu == &MP_RoomDef || currentMenu == &MP_ConnectDef)
{
I_lock_mutex(&ms_QueryId_mutex);
{
ms_QueryId++;
}
I_unlock_mutex(ms_QueryId_mutex);
}
if (currentMenu == &MP_ConnectDef)
{
I_lock_mutex(&ms_ServerList_mutex);
{
if (ms_ServerList)
{
free(ms_ServerList);
ms_ServerList = NULL;
}
}
I_unlock_mutex(ms_ServerList_mutex);
}
#endif/*HAVE_THREADS*/
if (currentMenu->quitroutine)
{
// If you're going from a menu to itself, why are you running the quitroutine? You're not quitting it! -SH
......@@ -3832,6 +3863,19 @@ void M_Ticker(void)
if (currentMenu == &OP_ScreenshotOptionsDef)
M_SetupScreenshotMenu();
#ifdef HAVE_THREADS
I_lock_mutex(&ms_ServerList_mutex);
{
if (ms_ServerList)
{
CL_QueryServerList(ms_ServerList);
free(ms_ServerList);
ms_ServerList = NULL;
}
}
I_unlock_mutex(ms_ServerList_mutex);
#endif
}
//
......@@ -10407,22 +10451,65 @@ static INT32 menuRoomIndex = 0;
static void M_DrawRoomMenu(void)
{
static int frame = -12;
int dot_frame;
char text[4];
const char *rmotd;
const char *waiting_message;
int dots;
if (m_waiting_mode)
{
dot_frame = frame / 4;
dots = dot_frame + 3;
strcpy(text, " ");
if (dots > 0)
{
if (dot_frame < 0)
dot_frame = 0;
strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame));
}
if (++frame == 12)
frame = -12;
currentMenu->menuitems[0].text = text;
}
// use generic drawer for cursor, items and title
M_DrawGenericMenu();
V_DrawString(currentMenu->x - 16, currentMenu->y, V_YELLOWMAP, M_GetText("Select a room"));
M_DrawTextBox(144, 24, 20, 20);
if (m_waiting_mode == M_NOT_WAITING)
{
M_DrawTextBox(144, 24, 20, 20);
if (itemOn == 0)
rmotd = M_GetText("Don't connect to the Master Server.");
else
rmotd = room_list[itemOn-1].motd;
if (itemOn == 0)
rmotd = M_GetText("Don't connect to the Master Server.");
else
rmotd = room_list[itemOn-1].motd;
rmotd = V_WordWrap(0, 20*8, 0, rmotd);
V_DrawString(144+8, 32, V_ALLOWLOWERCASE|V_RETURN8, rmotd);
}
rmotd = V_WordWrap(0, 20*8, 0, rmotd);
V_DrawString(144+8, 32, V_ALLOWLOWERCASE|V_RETURN8, rmotd);
if (m_waiting_mode)
{
// Display a little "please wait" message.
M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3);
if (m_waiting_mode == M_WAITING_VERSION)
waiting_message = "Checking for updates...";
else
waiting_message = "Fetching room info...";
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, waiting_message);
V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait.");
}
}
static void M_DrawConnectMenu(void)
......@@ -10490,6 +10577,14 @@ static void M_DrawConnectMenu(void)
localservercount = serverlistcount;
M_DrawGenericMenu();
if (m_waiting_mode)
{
// Display a little "please wait" message.
M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Searching for servers...");
V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait.");
}
}
static boolean M_CancelConnect(void)
......@@ -10579,10 +10674,10 @@ void M_SortServerList(void)
#ifndef NONET
#ifdef UPDATE_ALERT
static boolean M_CheckMODVersion(void)
static boolean M_CheckMODVersion(int id)
{
char updatestring[500];
const char *updatecheck = GetMODVersion();
const char *updatecheck = GetMODVersion(id);
if(updatecheck)
{
sprintf(updatestring, UPDATE_ALERT_STRING, VERSIONSTRING, updatecheck);
......@@ -10591,7 +10686,62 @@ static boolean M_CheckMODVersion(void)
} else
return true;
}
#endif
#ifdef HAVE_THREADS
static void
Check_new_version_thread (int *id)
{
int hosting;
int ok;
ok = 0;
if (M_CheckMODVersion(*id))
{
I_lock_mutex(&ms_QueryId_mutex);
{
ok = ( *id == ms_QueryId );
}
I_unlock_mutex(ms_QueryId_mutex);
if (ok)
{
I_lock_mutex(&m_menu_mutex);
{
m_waiting_mode = M_WAITING_ROOMS;
hosting = ( currentMenu->prevMenu == &MP_ServerDef );
}
I_unlock_mutex(m_menu_mutex);
GetRoomsList(hosting, *id);
}
}
else
{
I_lock_mutex(&ms_QueryId_mutex);
{
ok = ( *id == ms_QueryId );
}
I_unlock_mutex(ms_QueryId_mutex);
}
if (ok)
{
I_lock_mutex(&m_menu_mutex);
{
if (m_waiting_mode)
{
m_waiting_mode = M_NOT_WAITING;
MP_RoomMenu[0].text = "<Offline Mode>";
}
}
I_unlock_mutex(m_menu_mutex);
}
free(id);
}
#endif/*HAVE_THREADS*/
#endif/*UPDATE_ALERT*/
static void M_ConnectMenu(INT32 choice)
{
......@@ -10627,11 +10777,14 @@ static void M_ConnectMenuModChecks(INT32 choice)
M_ConnectMenu(-1);
}
static UINT32 roomIds[NUM_LIST_ROOMS];
UINT32 roomIds[NUM_LIST_ROOMS];
static void M_RoomMenu(INT32 choice)
{
INT32 i;
#ifdef HAVE_THREADS
int *id;
#endif
(void)choice;
......@@ -10644,34 +10797,47 @@ static void M_RoomMenu(INT32 choice)
if (rendermode == render_soft)
I_FinishUpdate(); // page flip or blit buffer
if (GetRoomsList(currentMenu == &MP_ServerDef) < 0)
return;
#ifdef UPDATE_ALERT
if (!M_CheckMODVersion())
return;
#endif
for (i = 1; i < NUM_LIST_ROOMS+1; ++i)
MP_RoomMenu[i].status = IT_DISABLED;
memset(roomIds, 0, sizeof(roomIds));
for (i = 0; room_list[i].header.buffer[0]; i++)
MP_RoomDef.prevMenu = currentMenu;
M_SetupNextMenu(&MP_RoomDef);
#ifdef UPDATE_ALERT
#ifdef HAVE_THREADS
m_waiting_mode = M_WAITING_VERSION;
MP_RoomMenu[0].text = "";
id = malloc(sizeof *id);
I_lock_mutex(&ms_QueryId_mutex);
{
if(*room_list[i].name != '\0')
{
MP_RoomMenu[i+1].text = room_list[i].name;
roomIds[i] = room_list[i].id;
MP_RoomMenu[i+1].status = IT_STRING|IT_CALL;
}
*id = ms_QueryId;
}
I_unlock_mutex(ms_QueryId_mutex);
MP_RoomDef.prevMenu = currentMenu;
M_SetupNextMenu(&MP_RoomDef);
I_spawn_thread("check-new-version",
(I_thread_fn)Check_new_version_thread, id);
#else/*HAVE_THREADS*/
if (M_CheckMODVersion(0))
{
GetRoomsList(currentMenu->prevMenu == &MP_ServerDef, 0);
}
#endif/*HAVE_THREADS*/
#endif/*UPDATE_ALERT*/
}