Kart-Public/src/mserv.c

568 lines
9.4 KiB
C
Raw Normal View History

2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
2018-11-25 12:35:38 +00:00
// Copyright (C) 1999-2018 by Sonic Team Junior.
2020-04-14 05:23:01 +00:00
// Copyright (C) 2020 by James R.
2014-03-15 16:59:03 +00:00
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file mserv.c
2020-04-14 04:20:29 +00:00
/// \brief Commands used to communicate with the master server
2014-03-15 16:59:03 +00:00
#if !defined (UNDER_CE)
#include <time.h>
#endif
#include "doomstat.h"
#include "doomdef.h"
#include "command.h"
#include "i_threads.h"
2014-03-15 16:59:03 +00:00
#include "mserv.h"
#include "m_menu.h"
2020-04-14 05:23:01 +00:00
#include "z_zone.h"
2014-03-15 16:59:03 +00:00
#ifdef HAVE_DISCORDRPC
#include "discord.h"
#endif
#ifdef MASTERSERVER
static int MSId;
static int MSRegisteredId = -1;
2014-03-15 16:59:03 +00:00
static boolean MSRegistered;
static boolean MSInProgress;
static boolean MSUpdateAgain;
2014-03-15 16:59:03 +00:00
static time_t MSLastPing;
2014-03-15 16:59:03 +00:00
#ifdef HAVE_THREADS
static I_mutex MSMutex;
static I_cond MSCond;
# define Lock_state() I_lock_mutex (&MSMutex)
# define Unlock_state() I_unlock_mutex (MSMutex)
#else/*HAVE_THREADS*/
# define Lock_state()
# define Unlock_state()
#endif/*HAVE_THREADS*/
2014-03-15 16:59:03 +00:00
#ifndef NONET
static void Command_Listserv_f(void);
#endif
#endif/*MASTERSERVER*/
static void Update_parameters (void);
2014-03-15 16:59:03 +00:00
static void MasterServer_OnChange(void);
static void Advertise_OnChange(void);
static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
{2, "MIN"},
{60, "MAX"},
2020-08-24 04:58:14 +00:00
{0, NULL}
};
2014-03-15 16:59:03 +00:00
2020-09-12 00:39:01 +00:00
consvar_t cv_masterserver = {"masterserver", "https://ms.kartkrew.org/ms/api", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_servername = {"servername", "SRB2Kart server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_server_contact = {"server_contact", "", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
2014-03-15 16:59:03 +00:00
consvar_t cv_masterserver_update_rate = {"masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, MasterClient_Ticker, 0, NULL, NULL, 0, 0, NULL};
2014-03-15 16:59:03 +00:00
consvar_t cv_advertise = {"advertise", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, Advertise_OnChange, 0, NULL, NULL, 0, 0, NULL};
2014-03-15 16:59:03 +00:00
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
int ms_QueryId;
I_mutex ms_QueryId_mutex;
2014-03-15 16:59:03 +00:00
msg_server_t *ms_ServerList;
I_mutex ms_ServerList_mutex;
2014-03-15 16:59:03 +00:00
#endif
UINT16 current_port = 0;
/** Adds variables and commands relating to the master server.
*
* \sa cv_masterserver, cv_servername,
* Command_Listserv_f
*/
void AddMServCommands(void)
{
#ifndef NONET
CV_RegisterVar(&cv_masterserver);
CV_RegisterVar(&cv_masterserver_update_rate);
2020-05-15 20:20:40 +00:00
CV_RegisterVar(&cv_masterserver_timeout);
CV_RegisterVar(&cv_masterserver_debug);
2020-06-13 06:47:08 +00:00
CV_RegisterVar(&cv_masterserver_token);
CV_RegisterVar(&cv_advertise);
2014-03-15 16:59:03 +00:00
CV_RegisterVar(&cv_servername);
CV_RegisterVar(&cv_server_contact);
#ifdef MASTERSERVER
2014-03-15 16:59:03 +00:00
COM_AddCommand("listserv", Command_Listserv_f);
#endif
#endif
2014-03-15 16:59:03 +00:00
}
#ifdef MASTERSERVER
2020-04-14 05:23:01 +00:00
static void WarnGUI (void)
2014-03-15 16:59:03 +00:00
{
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
2014-03-15 16:59:03 +00:00
#endif
2020-04-14 05:23:01 +00:00
M_StartMessage(M_GetText("There was a problem connecting to\nthe Master Server\n\nCheck the console for details.\n"), NULL, MM_NOTHING);
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
2014-03-15 16:59:03 +00:00
#endif
}
#define NUM_LIST_SERVER MAXSERVERLIST
msg_server_t *GetShortServersList(int id)
2014-03-15 16:59:03 +00:00
{
msg_server_t *server_list;
2014-03-15 16:59:03 +00:00
// +1 for easy test
server_list = malloc(( NUM_LIST_SERVER + 1 ) * sizeof *server_list);
2014-03-15 16:59:03 +00:00
if (HMS_fetch_servers(server_list, id))
return server_list;
2020-04-14 05:23:01 +00:00
else
2014-03-15 16:59:03 +00:00
{
free(server_list);
2020-04-14 05:23:01 +00:00
WarnGUI();
2014-03-15 16:59:03 +00:00
return NULL;
}
}
#ifdef UPDATE_ALERT
char *GetMODVersion(int id)
2014-03-15 16:59:03 +00:00
{
char *buffer;
2020-04-14 05:23:01 +00:00
int c;
2014-03-15 16:59:03 +00:00
(void)id;
2014-03-15 16:59:03 +00:00
buffer = malloc(16);
2014-03-15 16:59:03 +00:00
c = HMS_compare_mod_version(buffer, 16);
2014-03-15 16:59:03 +00:00
#ifdef HAVE_THREADS
I_lock_mutex(&ms_QueryId_mutex);
2014-03-15 16:59:03 +00:00
{
if (id != ms_QueryId)
c = -1;
}
I_unlock_mutex(ms_QueryId_mutex);
2014-03-15 16:59:03 +00:00
#endif
2020-04-14 05:23:01 +00:00
if (c > 0)
return buffer;
else
{
free(buffer);
2014-03-15 16:59:03 +00:00
2020-04-14 05:23:01 +00:00
if (! c)
WarnGUI();
2014-03-15 16:59:03 +00:00
return NULL;
}
}
#endif
#ifndef NONET
/** Gets a list of game servers. Called from console.
*/
static void Command_Listserv_f(void)
{
CONS_Printf(M_GetText("Retrieving server list...\n"));
{
HMS_list_servers();
2014-03-15 16:59:03 +00:00
}
}
#endif
static void
Finish_registration (void)
2014-03-15 16:59:03 +00:00
{
int registered;
2014-03-15 16:59:03 +00:00
CONS_Printf("Registering this server on the master server...\n");
2014-03-15 16:59:03 +00:00
registered = HMS_register();
2014-03-15 16:59:03 +00:00
Lock_state();
2014-03-15 16:59:03 +00:00
{
MSRegistered = registered;
MSRegisteredId = MSId;
time(&MSLastPing);
2014-03-15 16:59:03 +00:00
}
Unlock_state();
if (registered)
CONS_Printf("Master server registration successful.\n");
2014-03-15 16:59:03 +00:00
}
static void
Finish_update (void)
2014-03-15 16:59:03 +00:00
{
int registered;
int done;
2014-03-15 16:59:03 +00:00
Lock_state();
2014-03-15 16:59:03 +00:00
{
registered = MSRegistered;
MSUpdateAgain = false;/* this will happen anyway */
2014-03-15 16:59:03 +00:00
}
Unlock_state();
2014-03-15 16:59:03 +00:00
if (registered)
{
if (HMS_update())
{
Lock_state();
{
time(&MSLastPing);
MSRegistered = true;
}
Unlock_state();
CONS_Printf("Updated master server listing.\n");
}
else
Finish_registration();
}
else
Finish_registration();
2014-03-15 16:59:03 +00:00
Lock_state();
2014-03-15 16:59:03 +00:00
{
done = ! MSUpdateAgain;
if (done)
MSInProgress = false;
2014-03-15 16:59:03 +00:00
}
Unlock_state();
if (! done)
Finish_update();
2020-08-17 06:05:16 +00:00
#ifdef HAVE_DISCORDRPC
else
DRPC_UpdatePresence();
#endif
2014-03-15 16:59:03 +00:00
}
static void
Finish_unlist (void)
2014-03-15 16:59:03 +00:00
{
int registered;
2014-03-15 16:59:03 +00:00
Lock_state();
2014-03-15 16:59:03 +00:00
{
registered = MSRegistered;
if (MSId == MSRegisteredId)
MSId++;
2014-03-15 16:59:03 +00:00
}
Unlock_state();
2014-03-15 16:59:03 +00:00
if (registered)
{
CONS_Printf("Removing this server from the master server...\n");
if (HMS_unlist())
CONS_Printf("Server deregistration request successfully sent.\n");
2014-03-15 16:59:03 +00:00
Lock_state();
{
MSRegistered = false;
}
Unlock_state();
2014-03-15 16:59:03 +00:00
#ifdef HAVE_THREADS
I_wake_all_cond(&MSCond);
2014-03-15 16:59:03 +00:00
#endif
}
2020-08-17 06:05:16 +00:00
#ifdef HAVE_DISCORDRPC
DRPC_UpdatePresence();
#endif
2014-03-15 16:59:03 +00:00
}
#ifdef HAVE_THREADS
static int *
Server_id (void)
2014-03-15 16:59:03 +00:00
{
int *id;
id = malloc(sizeof *id);
Lock_state();
2014-03-15 16:59:03 +00:00
{
*id = MSId;
2014-03-15 16:59:03 +00:00
}
Unlock_state();
return id;
2014-03-15 16:59:03 +00:00
}
static int *
New_server_id (void)
2014-03-15 16:59:03 +00:00
{
int *id;
id = malloc(sizeof *id);
Lock_state();
{
*id = ++MSId;
I_wake_all_cond(&MSCond);
}
Unlock_state();
return id;
2014-03-15 16:59:03 +00:00
}
static void
Register_server_thread (int *id)
2014-03-15 16:59:03 +00:00
{
int same;
2014-03-15 16:59:03 +00:00
Lock_state();
2014-03-15 16:59:03 +00:00
{
/* wait for previous unlist to finish */
while (*id == MSId && MSRegistered)
I_hold_cond(&MSCond, MSMutex);
2014-03-15 16:59:03 +00:00
same = ( *id == MSId );/* it could have been a while */
2014-03-15 16:59:03 +00:00
}
Unlock_state();
2014-03-15 16:59:03 +00:00
if (same)/* it could have been a while */
Finish_registration();
2014-03-15 16:59:03 +00:00
free(id);
2014-03-15 16:59:03 +00:00
}
static void
Update_server_thread (int *id)
2014-03-15 16:59:03 +00:00
{
int same;
2014-03-15 16:59:03 +00:00
Lock_state();
{
same = ( *id == MSRegisteredId );
}
Unlock_state();
2014-03-15 16:59:03 +00:00
if (same)
Finish_update();
2014-03-15 16:59:03 +00:00
free(id);
2014-03-15 16:59:03 +00:00
}
static void
Unlist_server_thread (int *id)
2014-03-15 16:59:03 +00:00
{
int same;
2014-03-15 16:59:03 +00:00
Lock_state();
2014-03-15 16:59:03 +00:00
{
same = ( *id == MSRegisteredId );
2014-03-15 16:59:03 +00:00
}
Unlock_state();
2014-03-15 16:59:03 +00:00
if (same)
Finish_unlist();
2014-03-15 16:59:03 +00:00
free(id);
2014-03-15 16:59:03 +00:00
}
2020-04-28 21:21:57 +00:00
static void
Change_masterserver_thread (char *api)
2014-03-15 16:59:03 +00:00
{
2020-04-28 21:21:57 +00:00
Lock_state();
2014-03-15 16:59:03 +00:00
{
2020-04-28 21:21:57 +00:00
while (MSRegistered)
I_hold_cond(&MSCond, MSMutex);
2014-03-15 16:59:03 +00:00
}
2020-04-28 21:21:57 +00:00
Unlock_state();
2014-03-15 16:59:03 +00:00
2020-04-28 21:21:57 +00:00
HMS_set_api(api);
2014-03-15 16:59:03 +00:00
}
#endif/*HAVE_THREADS*/
2014-03-15 16:59:03 +00:00
void RegisterServer(void)
{
#ifdef MASTERSERVER
#ifdef HAVE_THREADS
I_spawn_thread(
"register-server",
(I_thread_fn)Register_server_thread,
New_server_id()
);
#else
Finish_registration();
#endif
#endif/*MASTERSERVER*/
}
2014-03-15 16:59:03 +00:00
static void UpdateServer(void)
{
#ifdef HAVE_THREADS
I_spawn_thread(
"update-server",
(I_thread_fn)Update_server_thread,
Server_id()
);
#else
Finish_update();
#endif
}
2014-03-15 16:59:03 +00:00
void UnregisterServer(void)
{
#ifdef MASTERSERVER
#ifdef HAVE_THREADS
I_spawn_thread(
"unlist-server",
(I_thread_fn)Unlist_server_thread,
Server_id()
);
#else
Finish_unlist();
#endif
#endif/*MASTERSERVER*/
2014-03-15 16:59:03 +00:00
}
static boolean
Online (void)
2014-03-15 16:59:03 +00:00
{
return ( serverrunning && cv_advertise.value );
}
2014-03-15 16:59:03 +00:00
static inline void SendPingToMasterServer(void)
{
int ready;
time_t now;
2014-03-15 16:59:03 +00:00
if (Online())
{
time(&now);
2014-03-15 16:59:03 +00:00
Lock_state();
{
ready = (
MSRegisteredId == MSId &&
! MSInProgress &&
2020-04-28 21:35:03 +00:00
now >= ( MSLastPing + 60 * cv_masterserver_update_rate.value )
);
if (ready)
MSInProgress = true;
}
Unlock_state();
2014-03-15 16:59:03 +00:00
if (ready)
UpdateServer();
2014-03-15 16:59:03 +00:00
}
}
void MasterClient_Ticker(void)
{
#ifdef MASTERSERVER
SendPingToMasterServer();
#endif
}
static void
Set_api (const char *api)
{
#ifdef HAVE_THREADS
I_spawn_thread(
"change-masterserver",
(I_thread_fn)Change_masterserver_thread,
strdup(api)
);
#else
HMS_set_api(strdup(api));
#endif
}
#endif/*MASTERSERVER*/
static void
Update_parameters (void)
2014-03-15 16:59:03 +00:00
{
#ifdef MASTERSERVER
int registered;
int delayed;
2014-03-15 16:59:03 +00:00
if (Online())
2014-03-15 16:59:03 +00:00
{
Lock_state();
{
delayed = MSInProgress;
2014-03-15 16:59:03 +00:00
if (delayed)/* do another update after the current one */
MSUpdateAgain = true;
else
registered = MSRegistered;
}
Unlock_state();
2014-03-15 16:59:03 +00:00
if (! delayed && registered)
UpdateServer();
2014-03-15 16:59:03 +00:00
}
#endif/*MASTERSERVER*/
2014-03-15 16:59:03 +00:00
}
static void MasterServer_OnChange(void)
{
#ifdef MASTERSERVER
2014-03-15 16:59:03 +00:00
UnregisterServer();
/*
TODO: remove this for v2, it's just a hack
for those coming in with an old config.
*/
if (
! cv_masterserver.changed &&
strcmp(cv_masterserver.string, "ms.srb2.org:28900") == 0
){
CV_StealthSet(&cv_masterserver, cv_masterserver.defaultvalue);
2014-03-15 16:59:03 +00:00
}
2020-04-28 21:21:57 +00:00
Set_api(cv_masterserver.string);
2020-04-14 05:23:01 +00:00
2020-04-28 21:21:57 +00:00
if (Online())
2020-04-14 05:23:01 +00:00
RegisterServer();
#endif/*MASTERSERVER*/
2014-03-15 16:59:03 +00:00
}
static void
Advertise_OnChange(void)
{
int different;
if (cv_advertise.value)
{
if (serverrunning)
{
Lock_state();
{
different = ( MSId != MSRegisteredId );
}
Unlock_state();
if (different)
{
RegisterServer();
}
}
}
else
{
UnregisterServer();
}
}