diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 2ab9a4f3443a837ae8c54cd4c32929b0975c230b..398083a79c3c3afa59e17d6ff49c2032488f3217 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -1764,10 +1764,6 @@ static void SendAskInfo(INT32 node, boolean viams)
 	// now allowed traffic from the host to us in, so once the MS relays
 	// our address to the host, it'll be able to speak to us.
 	HSendPacket(node, false, 0, sizeof (askinfo_pak));
-
-	// Also speak to the MS.
-	if (viams && node != 0 && node != BROADCASTADDR)
-		SendAskInfoViaMS(node, asktime);
 }
 
 serverelem_t serverlist[MAXSERVERLIST];
@@ -1830,7 +1826,6 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
 
 	if (!netgame && I_NetOpenSocket)
 	{
-		MSCloseUDPSocket();		// Tidy up before wiping the slate.
 		if (I_NetOpenSocket())
 		{
 			netgame = true;
@@ -2567,7 +2562,6 @@ static void Command_connect(void)
 		}
 		else if (I_NetOpenSocket)
 		{
-			MSCloseUDPSocket(); // Tidy up before wiping the slate.
 			I_NetOpenSocket();
 			netgame = true;
 			multiplayer = true;
@@ -3637,7 +3631,6 @@ boolean SV_SpawnServer(void)
 		SV_GenContext();
 		if (netgame && I_NetOpenSocket)
 		{
-			MSCloseUDPSocket();		// Tidy up before wiping the slate.
 			I_NetOpenSocket();
 			if (ms_RoomId > 0)
 				RegisterServer();
diff --git a/src/hms123311.c b/src/hms123311.c
index 13466dc859a84cd67e0134c3b027def00cd2af18..be0df42a3838bea55a1dbea797bf534ff03fa058 100644
--- a/src/hms123311.c
+++ b/src/hms123311.c
@@ -27,14 +27,6 @@ Documentation available here.
 #define Blame( ... ) \
 	CONS_Printf("\x85" __VA_ARGS__)
 
-consvar_t cv_http_masterserver = {
-	"http_masterserver",
-	"https://mb.srb2.org/MS/0",
-	CV_SAVE,
-
-	NULL, NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
-};
-
 consvar_t cv_masterserver_debug = {
 	"masterserver_debug", "Off", CV_SAVE, CV_OnOff,
 	NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
@@ -108,13 +100,13 @@ HMS_connect (const char *format, ...)
 		return NULL;
 	}
 
-	seek = strlen(cv_http_masterserver.string) + 1;/* + '/' */
+	seek = strlen(ms_API) + 1;/* + '/' */
 
 	va_start (ap, format);
 	url = ZZ_Alloc(seek + vsnprintf(0, 0, format, ap) + 1);
 	va_end (ap);
 
-	sprintf(url, "%s/", cv_http_masterserver.string);
+	sprintf(url, "%s/", ms_API);
 
 	va_start (ap, format);
 	vsprintf(&url[seek], format, ap);
@@ -200,15 +192,10 @@ HMS_end (struct HMS_buffer *buffer)
 }
 
 int
-HMS_in_use (void)
-{
-	return cv_http_masterserver.string[0];
-}
-
-void
 HMS_fetch_rooms (int joining)
 {
 	struct HMS_buffer *hms;
+	int ok;
 
 	char *id;
 	char *title;
@@ -248,9 +235,15 @@ HMS_fetch_rooms (int joining)
 		}
 
 		room_list[i].header.buffer[0] = 0;
+
+		ok = 1;
 	}
+	else
+		ok = 0;
 
 	HMS_end(hms);
+
+	return ok;
 }
 
 int
@@ -312,10 +305,11 @@ HMS_unlist (void)
 	Z_Free(hms_server_token);
 }
 
-void
+int
 HMS_update (void)
 {
 	struct HMS_buffer *hms;
+	int ok;
 
 	char post[256];
 
@@ -334,8 +328,10 @@ HMS_update (void)
 
 	curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post);
 
-	HMS_do(hms);
+	ok = HMS_do(hms);
 	HMS_end(hms);
+
+	return ok;
 }
 
 void
@@ -359,7 +355,7 @@ HMS_list_servers (void)
 	HMS_end(hms);
 }
 
-void
+msg_server_t *
 HMS_fetch_servers (msg_server_t *list, int room_number)
 {
 	struct HMS_buffer *hms;
@@ -452,22 +448,27 @@ HMS_fetch_servers (msg_server_t *list, int room_number)
 
 		list[i].header.buffer[0] = 0;
 	}
+	else
+		list = NULL;
 
 	HMS_end(hms);
+
+	return list;
 }
 
-const char *
-HMS_compare_mod_version (void)
+int
+HMS_compare_mod_version (char *buffer, size_t buffer_size)
 {
-	static char buffer[16];
-
 	struct HMS_buffer *hms;
+	int ok;
 
 	char *version;
 	char *version_name;
 
 	hms = HMS_connect("versions/%d", MODID);
 
+	ok = 0;
+
 	if (HMS_do(hms))
 	{
 		version      = strtok(hms->buffer, " ");
@@ -477,17 +478,15 @@ HMS_compare_mod_version (void)
 		{
 			if (atoi(version) != MODVERSION)
 			{
-				strlcpy(buffer, version_name, sizeof buffer);
-				version_name = buffer;
+				strlcpy(buffer, version_name, buffer_size);
+				ok = 1;
 			}
 			else
-				version_name = NULL;
+				ok = -1;
 		}
 	}
-	else
-		version_name = NULL;
 
 	HMS_end(hms);
 
-	return version_name;
+	return ok;
 }
diff --git a/src/m_menu.c b/src/m_menu.c
index 97b1ce9b5c1bee155f1e1f08db2911a68503113d..8025f91d4eafd857440db891c94208fc4f6ca5e8 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -2892,7 +2892,6 @@ boolean M_Responder(event_t *ev)
 				//make sure the game doesn't still think we're in a netgame.
 				if (!Playing() && netgame && multiplayer)
 				{
-					MSCloseUDPSocket();		// Clean up so we can re-open the connection later.
 					netgame = false;
 					multiplayer = false;
 				}
diff --git a/src/mserv.c b/src/mserv.c
index cfa526e1e2b09a9104ae70a4dfead01344bd2aa7..8cf656820ef7f4c9cbae51f53bbe8725a99a8c55 100644
--- a/src/mserv.c
+++ b/src/mserv.c
@@ -2,6 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1998-2000 by DooM Legacy Team.
 // Copyright (C) 1999-2018 by Sonic Team Junior.
+// Copyright (C)      2020 by James R.
 //
 // This program is free software distributed under the
 // terms of the GNU General Public License, version 2.
@@ -10,244 +11,45 @@
 /// \file  mserv.c
 /// \brief Commands used to communicate with the master server
 
-#ifdef __GNUC__
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#endif
-
 #if !defined (UNDER_CE)
 #include <time.h>
 #endif
 
-#if (defined (NOMD5) || defined (NOMSERV)) && !defined (NONET)
-#define NONET
-#endif
-
-#ifndef NONET
-
-#ifndef NO_IPV6
-#define HAVE_IPV6
-#endif
-
-#if (defined (_WIN32) || defined (_WIN32_WCE)) && !defined (_XBOX)
-#define RPC_NO_WINDOWS_H
-#ifdef HAVE_IPV6
-#include <ws2tcpip.h>
-#else
-#include <winsock.h>     // socket(),...
-#endif //!HAVE_IPV6
-#else
-#ifdef __OS2__
-#include <sys/types.h>
-#endif // __OS2__
-
-#ifdef HAVE_LWIP
-#include <lwip/inet.h>
-#include <kos/net.h>
-#include <lwip/lwip.h>
-#define ioctl lwip_ioctl
-#else
-#include <arpa/inet.h>
-#ifdef __APPLE_CC__
-#ifndef _BSD_SOCKLEN_T_
-#define _BSD_SOCKLEN_T_
-#endif
-#endif
-#include <sys/socket.h> // socket(),...
-#include <netinet/in.h> // sockaddr_in
-#ifdef _PS3
-#include <net/select.h>
-#elif !defined(_arch_dreamcast)
-#include <netdb.h> // getaddrinfo(),...
-#include <sys/ioctl.h>
-#endif
-#endif
-
-#ifdef _arch_dreamcast
-#include "sdl12/SRB2DC/dchelp.h"
-#endif
-
-#include <sys/time.h> // timeval,... (TIMEOUT)
-#include <errno.h>
-#endif // _WIN32/_WIN32_WCE
-
-#ifdef __OS2__
-#include <errno.h>
-#endif // __OS2__
-#endif // !NONET
-
 #include "doomstat.h"
 #include "doomdef.h"
 #include "command.h"
-#include "i_net.h"
-#include "console.h"
 #include "mserv.h"
-#include "d_net.h"
-#include "i_tcp.h"
-#include "i_system.h"
-#include "byteptr.h"
 #include "m_menu.h"
-#include "m_argv.h" // Alam is going to kill me <3
-#include "m_misc.h" //  GetRevisionString()
-
-#ifdef _WIN32_WCE
-#include "sdl12/SRB2CE/cehelp.h"
-#endif
-
-#include "i_addrinfo.h"
+#include "z_zone.h"
 
 /* HTTP */
 int  HMS_in_use (void);
-void HMS_fetch_rooms (int joining);
+int  HMS_fetch_rooms (int joining);
 int  HMS_register (void);
 void HMS_unlist (void);
-void HMS_update (void);
+int  HMS_update (void);
 void HMS_list_servers (void);
-void HMS_fetch_servers (msg_server_t *list, int room);
-const char * HMS_compare_mod_version (void);
-
-// ================================ DEFINITIONS ===============================
-
-#define PACKET_SIZE 1024
-
-
-#define  MS_NO_ERROR            	   0
-#define  MS_SOCKET_ERROR        	-201
-#define  MS_CONNECT_ERROR       	-203
-#define  MS_WRITE_ERROR         	-210
-#define  MS_READ_ERROR          	-211
-#define  MS_CLOSE_ERROR         	-212
-#define  MS_GETHOSTBYNAME_ERROR 	-220
-#define  MS_GETHOSTNAME_ERROR   	-221
-#define  MS_TIMEOUT_ERROR       	-231
-
-// see master server code for the values
-#define ADD_SERVER_MSG          	101
-#define REMOVE_SERVER_MSG       	103
-#define ADD_SERVERv2_MSG        	104
-#define GET_SERVER_MSG          	200
-#define GET_SHORT_SERVER_MSG    	205
-#define ASK_SERVER_MSG          	206
-#define ANSWER_ASK_SERVER_MSG   	207
-#define ASK_SERVER_MSG          	206
-#define ANSWER_ASK_SERVER_MSG   	207
-#define GET_MOTD_MSG            	208
-#define SEND_MOTD_MSG           	209
-#define GET_ROOMS_MSG           	210
-#define SEND_ROOMS_MSG          	211
-#define GET_ROOMS_HOST_MSG      	212
-#define GET_VERSION_MSG         	213
-#define SEND_VERSION_MSG        	214
-#define GET_BANNED_MSG          	215 // Someone's been baaaaaad!
-#define PING_SERVER_MSG         	216
-
-#define HEADER_SIZE (sizeof (INT32)*4)
-
-#define HEADER_MSG_POS    0
-#define IP_MSG_POS       16
-#define PORT_MSG_POS     32
-#define HOSTNAME_MSG_POS 40
-
-
-#if defined(_MSC_VER)
-#pragma pack(1)
-#endif
-
-/** A message to be exchanged with the master server.
-  */
-typedef struct
-{
-	INT32 id;                  ///< Unused?
-	INT32 type;                ///< Type of message.
-	INT32 room;                ///< Because everyone needs a roomie.
-	UINT32 length;             ///< Length of the message.
-	char buffer[PACKET_SIZE]; ///< Actual contents of the message.
-} ATTRPACK msg_t;
-
-#if defined(_MSC_VER)
-#pragma pack()
-#endif
+int  HMS_fetch_servers (msg_server_t *list, int room);
+int  HMS_compare_mod_version (char *buffer, size_t size_of_buffer);
 
-typedef struct Copy_CVarMS_t
-{
-	char ip[64];
-	char port[8];
-	char name[64];
-} Copy_CVarMS_s;
-static Copy_CVarMS_s registered_server;
 static time_t MSLastPing;
 
-#if defined(_MSC_VER)
-#pragma pack(1)
-#endif
-typedef struct
-{
-	char ip[16];         // Big enough to hold a full address.
-	UINT16 port;
-	UINT8 padding1[2];
-	tic_t time;
-} ATTRPACK ms_holepunch_packet_t;
-#if defined(_MSC_VER)
-#pragma pack()
-#endif
-
-// win32 or djgpp
-#if defined (_WIN32) || defined (_WIN32_WCE) || defined (__DJGPP__)
-#define ioctl ioctlsocket
-#define close closesocket
-#ifdef WATTCP
-#define strerror strerror_s
-#endif
-#if defined (_WIN32) || defined (_WIN32_WCE)
-#undef errno
-#define errno h_errno // some very strange things happen when not using h_error
-#endif
-#ifndef AI_ADDRCONFIG
-#define AI_ADDRCONFIG 0x00000400
-#endif
-#endif
-
 #ifndef NONET
 static void Command_Listserv_f(void);
 #endif
 static void MasterServer_OnChange(void);
 static void ServerName_OnChange(void);
 
-#define DEF_PORT "28900"
-consvar_t cv_masterserver = {"masterserver", "ms.srb2.org:"DEF_PORT, CV_SAVE, NULL, MasterServer_OnChange, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_masterserver = {"masterserver", "https://mb.srb2.org/MS/0", 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, ServerName_OnChange, 0, NULL, NULL, 0, 0, NULL};
 
+char *ms_API;
 INT16 ms_RoomId = -1;
 
 static enum { MSCS_NONE, MSCS_WAITING, MSCS_REGISTERED, MSCS_FAILED } con_state = MSCS_NONE;
 
-static INT32 msnode = -1;
 UINT16 current_port = 0;
 
-#if (defined (_WIN32) || defined (_WIN32_WCE) || defined (_WIN32)) && !defined (NONET)
-typedef SOCKET SOCKET_TYPE;
-#define ERRSOCKET (SOCKET_ERROR)
-#else
-#if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__) || defined (_PS3)
-typedef int SOCKET_TYPE;
-#else
-typedef unsigned long SOCKET_TYPE;
-#endif
-#define ERRSOCKET (-1)
-#endif
-
-#if (defined (WATTCP) && !defined (__libsocket_socklen_t)) || defined (_WIN32)
-typedef int socklen_t;
-#endif
-
-#ifndef NONET
-static SOCKET_TYPE socket_fd = ERRSOCKET; // WINSOCK socket
-static struct timeval select_timeout;
-static fd_set wset;
-static size_t recvfull(SOCKET_TYPE s, char *buf, size_t len, int flags);
-#endif
-
 // Room list is an external variable now.
 // Avoiding having to get info ten thousand times...
 msg_rooms_t room_list[NUM_LIST_ROOMS+1]; // +1 for easy test
@@ -261,304 +63,38 @@ void AddMServCommands(void)
 {
 #ifndef NONET
 	CV_RegisterVar(&cv_masterserver);
-	CV_RegisterVar(&cv_http_masterserver);
 	CV_RegisterVar(&cv_masterserver_debug);
 	CV_RegisterVar(&cv_servername);
 	COM_AddCommand("listserv", Command_Listserv_f);
 #endif
 }
 
-/** Closes the connection to the master server.
-  *
-  * \todo Fix for Windows?
-  */
-static void CloseConnection(void)
-{
-#ifndef NONET
-	if (socket_fd != (SOCKET_TYPE)ERRSOCKET)
-		close(socket_fd);
-	socket_fd = ERRSOCKET;
-#endif
-}
-
-//
-// MS_Write():
-//
-static INT32 MS_Write(msg_t *msg)
-{
-#ifdef NONET
-	(void)msg;
-	return MS_WRITE_ERROR;
-#else
-	size_t len;
-
-	if (msg->length == 0)
-		msg->length = (INT32)strlen(msg->buffer);
-	len = msg->length + HEADER_SIZE;
-
-	msg->type = htonl(msg->type);
-	msg->length = htonl(msg->length);
-	msg->room = htonl(msg->room);
-
-	if ((size_t)send(socket_fd, (char *)msg, (int)len, 0) != len)
-		return MS_WRITE_ERROR;
-	return 0;
-#endif
-}
-
-//
-// MS_Read():
-//
-static INT32 MS_Read(msg_t *msg)
-{
-#ifdef NONET
-	(void)msg;
-	return MS_READ_ERROR;
-#else
-	if (recvfull(socket_fd, (char *)msg, HEADER_SIZE, 0) != HEADER_SIZE)
-		return MS_READ_ERROR;
-
-	msg->type = ntohl(msg->type);
-	msg->length = ntohl(msg->length);
-	msg->room = ntohl(msg->room);
-
-	if (!msg->length) // fix a bug in Windows 2000
-		return 0;
-
-	if (recvfull(socket_fd, (char *)msg->buffer, msg->length, 0) != msg->length)
-		return MS_READ_ERROR;
-	return 0;
-#endif
-}
-
-#ifndef NONET
-/** Gets a list of game servers from the master server.
-  */
-static INT32 GetServersList(void)
-{
-	msg_t msg;
-	INT32 count = 0;
-
-	msg.type = GET_SERVER_MSG;
-	msg.length = 0;
-	msg.room = 0;
-	if (MS_Write(&msg) < 0)
-		return MS_WRITE_ERROR;
-
-	while (MS_Read(&msg) >= 0)
-	{
-		if (!msg.length)
-		{
-			if (!count)
-				CONS_Alert(CONS_NOTICE, M_GetText("No servers currently running.\n"));
-			return MS_NO_ERROR;
-		}
-		count++;
-		CONS_Printf("%s",msg.buffer);
-	}
-
-	return MS_READ_ERROR;
-}
-#endif
-
-//
-// MS_Connect()
-//
-static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
+static void WarnGUI (void)
 {
-#ifdef NONET
-	(void)ip_addr;
-	(void)str_port;
-	(void)async;
-#else
-	struct my_addrinfo *ai, *runp, hints;
-	int gaie;
-
-	memset (&hints, 0x00, sizeof(hints));
-#ifdef AI_ADDRCONFIG
-	hints.ai_flags = AI_ADDRCONFIG;
-#endif
-	hints.ai_family = AF_INET;
-	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_protocol = IPPROTO_TCP;
-
-	//I_InitTcpNetwork(); this is already done on startup in D_SRB2Main()
-	if (!I_InitTcpDriver()) // this is done only if not already done
-		return MS_SOCKET_ERROR;
-
-	gaie = I_getaddrinfo(ip_addr, str_port, &hints, &ai);
-	if (gaie != 0)
-		return MS_GETHOSTBYNAME_ERROR;
-	else
-		runp = ai;
-
-	while (runp != NULL)
-	{
-		socket_fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
-		if (socket_fd != (SOCKET_TYPE)ERRSOCKET)
-		{
-			if (async) // do asynchronous connection
-			{
-#ifdef FIONBIO
-#ifdef WATTCP
-				char res = 1;
-#else
-				unsigned long res = 1;
-#endif
-
-				ioctl(socket_fd, FIONBIO, &res);
-#endif
-
-				if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) == ERRSOCKET)
-				{
-#ifdef _WIN32 // humm, on win32/win64 it doesn't work with EINPROGRESS (stupid windows)
-					if (WSAGetLastError() != WSAEWOULDBLOCK)
-#else
-					if (errno != EINPROGRESS)
-#endif
-					{
-						con_state = MSCS_FAILED;
-						CloseConnection();
-						I_freeaddrinfo(ai);
-						return MS_CONNECT_ERROR;
-					}
-				}
-				con_state = MSCS_WAITING;
-				FD_ZERO(&wset);
-				FD_SET(socket_fd, &wset);
-				select_timeout.tv_sec = 0, select_timeout.tv_usec = 0;
-				I_freeaddrinfo(ai);
-				return 0;
-			}
-			else if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) != ERRSOCKET)
-			{
-				I_freeaddrinfo(ai);
-				return 0;
-			}
-		}
-		runp = runp->ai_next;
-	}
-	I_freeaddrinfo(ai);
-#endif
-	return MS_CONNECT_ERROR;
+	M_StartMessage(M_GetText("There was a problem connecting to\nthe Master Server\n\nCheck the console for details.\n"), NULL, MM_NOTHING);
 }
 
 #define NUM_LIST_SERVER MAXSERVERLIST
 const msg_server_t *GetShortServersList(INT32 room)
 {
 	static msg_server_t server_list[NUM_LIST_SERVER+1]; // +1 for easy test
-	msg_t msg;
-	INT32 i;
 
-	if (HMS_in_use())
-	{
-		HMS_fetch_servers(server_list, room);
+	if (HMS_fetch_servers(server_list, room))
 		return server_list;
-	}
-
-	// we must be connected to the master server before writing to it
-	if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
+	else
 	{
-		CONS_Alert(CONS_ERROR, M_GetText("Cannot connect to the Master Server\n"));
-		M_StartMessage(M_GetText("There was a problem connecting to\nthe Master Server\n"), NULL, MM_NOTHING);
-		return NULL;
-	}
-
-	msg.type = GET_SHORT_SERVER_MSG;
-	msg.length = 0;
-	msg.room = room;
-	if (MS_Write(&msg) < 0)
+		WarnGUI();
 		return NULL;
-
-	for (i = 0; i < NUM_LIST_SERVER && MS_Read(&msg) >= 0; i++)
-	{
-		if (!msg.length)
-		{
-			server_list[i].header.buffer[0] = 0;
-			CloseConnection();
-			return server_list;
-		}
-		M_Memcpy(&server_list[i], msg.buffer, sizeof (msg_server_t));
-		server_list[i].header.buffer[0] = 1;
-	}
-	CloseConnection();
-	if (i == NUM_LIST_SERVER)
-	{
-		server_list[i].header.buffer[0] = 0;
-		return server_list;
 	}
-	else
-		return NULL;
 }
 
 INT32 GetRoomsList(boolean hosting)
 {
-	static msg_ban_t banned_info[1];
-	msg_t msg;
-	INT32 i;
-
-	if (HMS_in_use())
-	{
-		HMS_fetch_rooms( ! hosting );
-		return 1;
-	}
-
-	// we must be connected to the master server before writing to it
-	if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Cannot connect to the Master Server\n"));
-		M_StartMessage(M_GetText("There was a problem connecting to\nthe Master Server\n"), NULL, MM_NOTHING);
-		return -1;
-	}
-
-	if (hosting)
-		msg.type = GET_ROOMS_HOST_MSG;
-	else
-		msg.type = GET_ROOMS_MSG;
-	msg.length = 0;
-	msg.room = 0;
-	if (MS_Write(&msg) < 0)
-	{
-		room_list[0].id = 1;
-		strcpy(room_list[0].motd,"Master Server Offline.");
-		strcpy(room_list[0].name,"Offline");
-		return -1;
-	}
-
-	for (i = 0; i < NUM_LIST_ROOMS && MS_Read(&msg) >= 0; i++)
-	{
-		if(msg.type == GET_BANNED_MSG)
-		{
-			char banmsg[1000];
-			M_Memcpy(&banned_info[0], msg.buffer, sizeof (msg_ban_t));
-			if (hosting)
-				sprintf(banmsg, M_GetText("You have been banned from\nhosting netgames.\n\nUnder the following IP Range:\n%s - %s\n\nFor the following reason:\n%s\n\nYour ban will expire on:\n%s"),banned_info[0].ipstart,banned_info[0].ipend,banned_info[0].reason,banned_info[0].endstamp);
-			else
-				sprintf(banmsg, M_GetText("You have been banned from\njoining netgames.\n\nUnder the following IP Range:\n%s - %s\n\nFor the following reason:\n%s\n\nYour ban will expire on:\n%s"),banned_info[0].ipstart,banned_info[0].ipend,banned_info[0].reason,banned_info[0].endstamp);
-			M_StartMessage(banmsg, NULL, MM_NOTHING);
-			ms_RoomId = -1;
-			return -2;
-		}
-		if (!msg.length)
-		{
-			room_list[i].header.buffer[0] = 0;
-			CloseConnection();
-			return 1;
-		}
-		M_Memcpy(&room_list[i], msg.buffer, sizeof (msg_rooms_t));
-		room_list[i].header.buffer[0] = 1;
-	}
-	CloseConnection();
-	if (i == NUM_LIST_ROOMS)
-	{
-		room_list[i].header.buffer[0] = 0;
+	if (HMS_fetch_rooms( ! hosting ))
 		return 1;
-	}
 	else
 	{
-		room_list[0].id = 1;
-		strcpy(room_list[0].motd,M_GetText("Master Server Offline."));
-		strcpy(room_list[0].name,M_GetText("Offline"));
+		WarnGUI();
 		return -1;
 	}
 }
@@ -566,88 +102,29 @@ INT32 GetRoomsList(boolean hosting)
 #ifdef UPDATE_ALERT
 const char *GetMODVersion(void)
 {
-	static msg_t msg;
+	static char buffer[16];
+	int c;
 
-	if (HMS_in_use())
-	{
-		return HMS_compare_mod_version();
-	}
-
-	// we must be connected to the master server before writing to it
-	if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Cannot connect to the Master Server\n"));
-		M_StartMessage(M_GetText("There was a problem connecting to\nthe Master Server\n"), NULL, MM_NOTHING);
-		return NULL;
-	}
+	c = HMS_compare_mod_version(buffer, sizeof buffer);
 
-	msg.type = GET_VERSION_MSG;
-	msg.length = sizeof MODVERSION;
-	msg.room = MODID; // Might as well use it for something.
-	sprintf(msg.buffer,"%d",MODVERSION);
-	if (MS_Write(&msg) < 0)
+	if (c > 0)
+		return buffer;
+	else
 	{
-		CONS_Alert(CONS_ERROR, M_GetText("Could not send to the Master Server\n"));
-		M_StartMessage(M_GetText("Could not send to the Master Server\n"), NULL, MM_NOTHING);
-		CloseConnection();
-		return NULL;
-	}
+		if (! c)
+			WarnGUI();
 
-	if (MS_Read(&msg) < 0)
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("No reply from the Master Server\n"));
-		M_StartMessage(M_GetText("No reply from the Master Server\n"), NULL, MM_NOTHING);
-		CloseConnection();
 		return NULL;
 	}
-
-	CloseConnection();
-
-	if(strcmp(msg.buffer,"NULL") != 0)
-	{
-		return msg.buffer;
-	}
-	else
-		return NULL;
 }
 
 // Console only version of the above (used before game init)
 void GetMODVersion_Console(void)
 {
-	static msg_t msg;
-
-	if (HMS_in_use())
-		return;
-
-	// we must be connected to the master server before writing to it
-	if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Cannot connect to the Master Server\n"));
-		return;
-	}
-
-	msg.type = GET_VERSION_MSG;
-	msg.length = sizeof MODVERSION;
-	msg.room = MODID; // Might as well use it for something.
-	sprintf(msg.buffer,"%d",MODVERSION);
-	if (MS_Write(&msg) < 0)
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Could not send to the Master Server\n"));
-		CloseConnection();
-		return;
-	}
-
-	if (MS_Read(&msg) < 0)
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("No reply from the Master Server\n"));
-		CloseConnection();
-		return;
-	}
-
-	CloseConnection();
+	char buffer[16];
 
-	if(strcmp(msg.buffer,"NULL") != 0)
-		I_Error(UPDATE_ALERT_STRING_CONSOLE, VERSIONSTRING, msg.buffer);
+	if (HMS_compare_mod_version(buffer, sizeof buffer) > 0)
+		I_Error(UPDATE_ALERT_STRING_CONSOLE, VERSIONSTRING, buffer);
 }
 #endif
 
@@ -656,390 +133,56 @@ void GetMODVersion_Console(void)
   */
 static void Command_Listserv_f(void)
 {
-	if (con_state == MSCS_WAITING)
-	{
-		CONS_Alert(CONS_NOTICE, M_GetText("Not yet connected to the Master Server.\n"));
-		return;
-	}
-
 	CONS_Printf(M_GetText("Retrieving server list...\n"));
 
-	if (HMS_in_use())
 	{
 		HMS_list_servers();
-		return;
-	}
-
-	if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Cannot connect to the Master Server\n"));
-		return;
-	}
-
-	if (GetServersList())
-		CONS_Alert(CONS_ERROR, M_GetText("Cannot get server list\n"));
-
-	CloseConnection();
-}
-#endif
-
-FUNCMATH static const char *int2str(INT32 n)
-{
-	INT32 i;
-	static char res[16];
-
-	res[15] = '\0';
-	res[14] = (char)((char)(n%10)+'0');
-	for (i = 13; (n /= 10); i--)
-		res[i] = (char)((char)(n%10)+'0');
-
-	return &res[i+1];
-}
-
-#ifndef NONET
-static INT32 ConnectionFailed(void)
-{
-	con_state = MSCS_FAILED;
-	CONS_Alert(CONS_ERROR, M_GetText("Connection to Master Server failed\n"));
-	CloseConnection();
-	return MS_CONNECT_ERROR;
-}
-#endif
-
-/** Tries to register the local game server on the master server.
-  */
-static INT32 AddToMasterServer(boolean firstadd)
-{
-#ifdef NONET
-	(void)firstadd;
-#else
-	static INT32 retry = 0;
-	int i, res;
-	socklen_t j;
-	msg_t msg;
-	msg_server_t *info = (msg_server_t *)msg.buffer;
-	INT32 room = -1;
-	fd_set tset;
-	time_t timestamp = time(NULL);
-	UINT32 signature, tmp;
-	const char *insname;
-
-	if (HMS_in_use())
-	{
-		HMS_update();
-		return MS_NO_ERROR;
-	}
-
-	M_Memcpy(&tset, &wset, sizeof (tset));
-	res = select(255, NULL, &tset, NULL, &select_timeout);
-	if (res != ERRSOCKET && !res)
-	{
-		if (retry++ > 30) // an about 30 second timeout
-		{
-			retry = 0;
-			CONS_Alert(CONS_ERROR, M_GetText("Master Server timed out\n"));
-			MSLastPing = timestamp;
-			return ConnectionFailed();
-		}
-		return MS_CONNECT_ERROR;
-	}
-	retry = 0;
-	/*
-	Somehow we can still select our old socket despite it being closed(?).
-	Atleast, that's what I THINK is happening. Anyway, we have to check that we
-	haven't open a socket, and actually open it!
-	*/
-	/*if (res == ERRSOCKET)*//* wtf? no! */
-	if (socket_fd == (SOCKET_TYPE)ERRSOCKET)
-	{
-		if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
-		{
-			CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno));
-			MSLastPing = timestamp;
-			return ConnectionFailed();
-		}
-	}
-
-	// so, the socket is writable, but what does that mean, that the connection is
-	// ok, or bad... let see that!
-	j = (socklen_t)sizeof (i);
-	getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j);
-	/*
-	This is also wrong. If getsockopt fails, i doesn't have to be set. Plus, if
-	it is set (which it appearantly is on linux), we check errno anyway. And in
-	the case that i is returned as normal, we don't even report the correct
-	value! So we accomplish NOTHING, except returning due to dumb luck.
-	If you care, fix this--I don't. -James (R.)
-	*/
-	if (i) // it was bad
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno));
-		MSLastPing = timestamp;
-		return ConnectionFailed();
-	}
-
-#ifdef PARANOIA
-	if (ms_RoomId <= 0)
-		I_Error("Attmepted to host in room \"All\"!\n");
-#endif
-	room = ms_RoomId;
-
-	for(signature = 0, insname = cv_servername.string; *insname; signature += *insname++);
-	tmp = (UINT32)(signature * (size_t)&MSLastPing);
-	signature *= tmp;
-	signature &= 0xAAAAAAAA;
-	M_Memcpy(&info->header.signature, &signature, sizeof (UINT32));
-
-	strcpy(info->ip, "");
-	strcpy(info->port, int2str(current_port));
-	strcpy(info->name, cv_servername.string);
-	M_Memcpy(&info->room, & room, sizeof (INT32));
-#if VERSION > 0 || SUBVERSION > 0
-	sprintf(info->version, "%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION);
-#else // Trunk build, send revision info
-	strcpy(info->version, GetRevisionString());
-#endif
-	strcpy(registered_server.name, cv_servername.string);
-
-	if(firstadd)
-		msg.type = ADD_SERVER_MSG;
-	else
-		msg.type = PING_SERVER_MSG;
-
-	msg.length = (UINT32)sizeof (msg_server_t);
-	msg.room = 0;
-	if (MS_Write(&msg) < 0)
-	{
-		MSLastPing = timestamp;
-		return ConnectionFailed();
-	}
-
-	if(con_state != MSCS_REGISTERED)
-		CONS_Printf(M_GetText("Master Server update successful.\n"));
-
-	MSLastPing = timestamp;
-	con_state = MSCS_REGISTERED;
-	CloseConnection();
-#endif
-	return MS_NO_ERROR;
-}
-
-static INT32 RemoveFromMasterSever(void)
-{
-	msg_t msg;
-	msg_server_t *info = (msg_server_t *)msg.buffer;
-
-	strcpy(info->header.buffer, "");
-	strcpy(info->ip, "");
-	strcpy(info->port, int2str(current_port));
-	strcpy(info->name, registered_server.name);
-	sprintf(info->version, "%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION);
-
-	msg.type = REMOVE_SERVER_MSG;
-	msg.length = (UINT32)sizeof (msg_server_t);
-	msg.room = 0;
-	if (MS_Write(&msg) < 0)
-		return MS_WRITE_ERROR;
-
-	return MS_NO_ERROR;
-}
-
-const char *GetMasterServerPort(void)
-{
-	const char *t = cv_masterserver.string;
-
-	while ((*t != ':') && (*t != '\0'))
-		t++;
-
-	if (*t)
-		return ++t;
-	else
-		return DEF_PORT;
-}
-
-/** Gets the IP address of the master server. Actually, it seems to just
-  * return the hostname, instead; the lookup is done elsewhere.
-  *
-  * \return Hostname of the master server, without port number on the end.
-  * \todo Rename function?
-  */
-const char *GetMasterServerIP(void)
-{
-	static char str_ip[64];
-	char *t = str_ip;
-
-	if (strstr(cv_masterserver.string, "srb2.ssntails.org:28910")
-	 || strstr(cv_masterserver.string, "srb2.servegame.org:28910")
-	 || strstr(cv_masterserver.string, "srb2.servegame.org:28900")
-	   )
-	{
-		// replace it with the current default one
-		CV_Set(&cv_masterserver, cv_masterserver.defaultvalue);
 	}
-
-	strcpy(t, cv_masterserver.string);
-
-	while ((*t != ':') && (*t != '\0'))
-		t++;
-	*t = '\0';
-
-	return str_ip;
 }
-
-void MSOpenUDPSocket(void)
-{
-#ifndef NONET
-	if (I_NetMakeNodewPort)
-	{
-		// If it's already open, there's nothing to do.
-		if (msnode < 0)
-			msnode = I_NetMakeNodewPort(GetMasterServerIP(), GetMasterServerPort());
-	}
-	else
 #endif
-		msnode = -1;
-}
-
-void MSCloseUDPSocket(void)
-{
-	if (msnode != INT16_MAX) I_NetFreeNodenum(msnode);
-	msnode = -1;
-}
 
 void RegisterServer(void)
 {
-	if (con_state == MSCS_REGISTERED || con_state == MSCS_WAITING)
-			return;
-
 	CONS_Printf(M_GetText("Registering this server on the Master Server...\n"));
 
-	if (HMS_in_use())
 	{
 		if (HMS_register())
 			con_state = MSCS_REGISTERED;
-		return;
+		else
+			con_state = MSCS_FAILED;
 	}
+}
 
-	strcpy(registered_server.ip, GetMasterServerIP());
-	strcpy(registered_server.port, GetMasterServerPort());
-
-	if (MS_Connect(registered_server.ip, registered_server.port, 1))
+static void UpdateServer(void)
+{
+	if (!( con_state == MSCS_REGISTERED && HMS_update() ))
 	{
-		CONS_Alert(CONS_ERROR, M_GetText("Cannot connect to the Master Server\n"));
-		return;
+		con_state = MSCS_FAILED;
+		RegisterServer();
 	}
-	MSOpenUDPSocket();
 
-	// keep the TCP connection open until AddToMasterServer() is completed;
+	time(&MSLastPing);
 }
 
 static inline void SendPingToMasterServer(void)
 {
-	if (HMS_in_use())
-		return;
-/*	static tic_t next_time = 0;
-	tic_t cur_time;
-	char *inbuffer = (char*)netbuffer;
-
-	cur_time = I_GetTime();
-	if (!netgame)
-		UnregisterServer();
-	else if (cur_time > next_time) // ping every 2 second if possible
-	{
-		next_time = cur_time+2*TICRATE;
-
-		if (con_state == MSCS_WAITING)
-			AddToMasterServer();
-
-		if (con_state != MSCS_REGISTERED)
-			return;
-
-		// cur_time is just a dummy data to send
-		WRITEUINT32(inbuffer, cur_time);
-		doomcom->datalength = sizeof (cur_time);
-		doomcom->remotenode = (INT16)msnode;
-		I_NetSend();
-	}
-*/
-
 // Here, have a simpler MS Ping... - Cue
 	if(time(NULL) > (MSLastPing+(60*2)) && con_state != MSCS_NONE)
 	{
-		//CONS_Debug(DBG_NETPLAY, "%ld (current time) is greater than %d (Last Ping Time)\n", time(NULL), MSLastPing);
-		if(MSLastPing < 1)
-			AddToMasterServer(true);
-		else
-			AddToMasterServer(false);
+		UpdateServer();
 	}
 }
 
-void SendAskInfoViaMS(INT32 node, tic_t asktime)
-{
-	const char *address;
-	UINT16 port;
-	char *inip;
-	ms_holepunch_packet_t mshpp;
-
-	MSOpenUDPSocket();
-
-	// This must be called after calling MSOpenUDPSocket, due to the
-	// static buffer.
-	address = I_GetNodeAddress(node);
-
-	// no address?
-	if (!address)
-		return;
-
-	// Copy the IP address into the buffer.
-	inip = mshpp.ip;
-	while(*address && *address != ':') *inip++ = *address++;
-	*inip = '\0';
-
-	// Get the port.
-	port = (UINT16)(*address++ ? atoi(address) : 0);
-	mshpp.port = SHORT(port);
-
-	// Set the time for ping calculation.
-	mshpp.time = LONG(asktime);
-
-	// Send to the MS.
-	M_Memcpy(netbuffer, &mshpp, sizeof(mshpp));
-	doomcom->datalength = sizeof(ms_holepunch_packet_t);
-	doomcom->remotenode = (INT16)msnode;
-	I_NetSend();
-}
-
 void UnregisterServer(void)
 {
-	if (con_state != MSCS_REGISTERED)
+	if (con_state == MSCS_REGISTERED)
 	{
-		con_state = MSCS_NONE;
-		CloseConnection();
-		return;
-	}
-
-	con_state = MSCS_NONE;
+		CONS_Printf(M_GetText("Removing this server from the Master Server...\n"));
 
-	CONS_Printf(M_GetText("Removing this server from the Master Server...\n"));
-
-	if (HMS_in_use())
-	{
 		HMS_unlist();
-		return;
 	}
 
-	if (MS_Connect(registered_server.ip, registered_server.port, 0))
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Cannot connect to the Master Server\n"));
-		return;
-	}
-
-	if (RemoveFromMasterSever() < 0)
-		CONS_Alert(CONS_ERROR, M_GetText("Cannot remove this server from the Master Server\n"));
-
-	CloseConnection();
-	MSCloseUDPSocket();
-	MSLastPing = 0;
+	con_state = MSCS_NONE;
 }
 
 void MasterClient_Ticker(void)
@@ -1051,33 +194,23 @@ void MasterClient_Ticker(void)
 static void ServerName_OnChange(void)
 {
 	if (con_state == MSCS_REGISTERED)
-		AddToMasterServer(false);
+		UpdateServer();
 }
 
 static void MasterServer_OnChange(void)
 {
-	UnregisterServer();
-	RegisterServer();
-}
+	boolean auto_register;
 
-#ifndef NONET
-// Like recv, but waits until we've got enough data to fill the buffer.
-static size_t recvfull(SOCKET_TYPE s, char *buf, size_t len, int flags)
-{
-	/* Total received. */
-	size_t totallen = 0;
+	auto_register = ( con_state != MSCS_NONE );
 
-	while(totallen < len)
+	if (ms_API)
 	{
-		ssize_t ret = (ssize_t)recv(s, buf + totallen, (int)(len - totallen), flags);
-
-		/* Error. */
-		if(ret == -1)
-			return (size_t)-1;
-
-		totallen += ret;
+		UnregisterServer();
+		Z_Free(ms_API);
 	}
 
-	return totallen;
+	ms_API = Z_StrDup(cv_masterserver.string);
+
+	if (auto_register)
+		RegisterServer();
 }
-#endif
diff --git a/src/mserv.h b/src/mserv.h
index 9f6f9ad30513e049df30087cdbbf478c73b28d13..3c3b2cf3117931eb261beda662b99431fe8765cc 100644
--- a/src/mserv.h
+++ b/src/mserv.h
@@ -2,6 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1998-2000 by DooM Legacy Team.
 // Copyright (C) 1999-2018 by Sonic Team Junior.
+// Copyright (C)      2020 by James R.
 //
 // This program is free software distributed under the
 // terms of the GNU General Public License, version 2.
@@ -13,7 +14,7 @@
 #ifndef _MSERV_H_
 #define _MSERV_H_
 
-#define MASTERSERVERS21 // MasterServer v2.1
+#define HMS123311 // don't mess with nights, man
 
 // lowered from 32 due to menu changes
 #define NUM_LIST_ROOMS 16
@@ -64,21 +65,14 @@ typedef struct
 // ================================ GLOBALS ===============================
 
 extern consvar_t cv_masterserver, cv_servername;
-extern consvar_t cv_http_masterserver;
 extern consvar_t cv_masterserver_debug;
 
+extern char *ms_API;
+
 // < 0 to not connect (usually -1) (offline mode)
 // == 0 to show all rooms, not a valid hosting room
 // anything else is whatever room the MS assigns to that number (online mode)
-INT16 ms_RoomId;
-
-const char *GetMasterServerPort(void);
-const char *GetMasterServerIP(void);
-
-void MSOpenUDPSocket(void);
-void MSCloseUDPSocket(void);
-
-void SendAskInfoViaMS(INT32 node, tic_t asktime);
+extern INT16 ms_RoomId;
 
 void RegisterServer(void);
 void UnregisterServer(void);