]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
Thanks to Elric for adding dpmaster support!
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 24 Sep 2002 12:16:28 +0000 (12:16 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 24 Sep 2002 12:16:28 +0000 (12:16 +0000)
slist command renamed to net_slist, net_inetslist command added
"heartbeat" command notifies master server(s) of your server's presence (this is automatic, but you can force a heartbeat)
sv_master1 through sv_master4 cvars contain master server addresses, they all default to "" (none), this may change if someone hosts a darkplaces master server and wants it added to the defaults...  (note: these cvars ARE saved to config)
com_modname contains the currently running mod directory name (for example id1, darkplaces, transfusion, etc)
some Con_DPrintf's have been added to the server query code, so if you want to know if people are checking out your server, it should tell you about it now (I think?)
some Con_DPrintf's exist in the inetslist code so you can watch the packet flow

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2432 d7cf8633-e32d-0410-b094-e92efae38249

23 files changed:
common.c
common.h
darkplaces.dsp
host.c
makefile
menu.c
net.h
net_bsd.c
net_dgrm.c
net_dgrm.h
net_loop.c
net_loop.h
net_main.c
net_master.c [new file with mode: 0644]
net_master.h [new file with mode: 0644]
net_udp.c
net_udp.h
net_win.c
net_wins.c
net_wins.h
net_wipx.c
net_wipx.h
sv_main.c

index af2161f5625474c639fe1d1bdf34e36613cc482e..0f413b2ddde0cc493ed19b662cfde10571388041 100644 (file)
--- a/common.c
+++ b/common.c
@@ -50,6 +50,7 @@ char com_cmdline[CMDLINE_LENGTH];
 int gamemode;
 char *gamename;
 char *gamedirname;
+char com_modname[MAX_OSPATH];
 
 /*
 
@@ -1425,10 +1426,12 @@ void COM_InitFilesystem (void)
                com_basedir[i-1] = 0;
 
 // start up with GAMENAME by default (id1)
+       strcpy(com_modname, GAMENAME);
        COM_AddGameDirectory (va("%s/"GAMENAME, com_basedir));
        if (gamedirname[0])
        {
                com_modified = true;
+               strcpy(com_modname, gamedirname);
                COM_AddGameDirectory (va("%s/%s", com_basedir, gamedirname));
        }
 
@@ -1438,6 +1441,7 @@ void COM_InitFilesystem (void)
        if (i && i < com_argc-1)
        {
                com_modified = true;
+               strcpy(com_modname, com_argv[i+1]);
                COM_AddGameDirectory (va("%s/%s", com_basedir, com_argv[i+1]));
        }
 
index 78b23a6a605de4630813b4a4905077dc92263a57..ce8b6eaf21d3c7134d4138c490a49e33b3f4c8f9 100644 (file)
--- a/common.h
+++ b/common.h
@@ -175,6 +175,7 @@ extern      struct cvar_s   registered;
 
 extern int gamemode;
 extern char *gamename;
+extern char com_modname[MAX_OSPATH];
 
 // LordHavoc: useful...
 void COM_ToLowerString(const char *in, char *out);
index 77ae9bd07d89c419acb7cfec2fd29e921ef7b8d6..b79f26a2eb5611e92af3da4b1037f6991ec8237c 100644 (file)
@@ -268,6 +268,10 @@ SOURCE=.\net_main.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\net_master.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\net_win.c\r
 # End Source File\r
 # Begin Source File\r
@@ -568,6 +572,10 @@ SOURCE=.\net_loop.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\net_master.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\net_wins.h\r
 # End Source File\r
 # Begin Source File\r
diff --git a/host.c b/host.c
index 9fcc9cf88191fff150a48a57c1620d6f93f1ff0c..42dca46c48112363dcabc8124e198c1125fa47e0 100644 (file)
--- a/host.c
+++ b/host.c
@@ -461,6 +461,8 @@ void SV_DropClient (qboolean crash)
                MSG_WriteByte (&client->message, host_client - svs.clients);
                MSG_WriteByte (&client->message, 0);
        }
+
+       NET_Heartbeat ();
 }
 
 /*
@@ -488,6 +490,9 @@ void Host_ShutdownServer(qboolean crash)
 // stop all client sounds immediately
        CL_Disconnect ();
 
+       NET_Heartbeat ();
+       NET_Heartbeat ();
+
 // flush any pending messages - like the score!!!
        start = Sys_DoubleTime();
        do
index 49c7edf7635448b6d1b1ab7f006c4a4d4975a30d..09a468c93be45c827c5dc609c32b1a9002b0f712 100644 (file)
--- a/makefile
+++ b/makefile
@@ -24,7 +24,7 @@ CD=cd_null.o
 
 CLIENTOBJECTS= cgame.o cgamevm.o chase.o cl_collision.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_particles.o cl_screen.o cl_video.o console.o dpvsimpledecode.o fractalnoise.o gl_backend.o gl_draw.o gl_models.o gl_rmain.o gl_rsurf.o gl_textures.o keys.o menu.o meshqueue.o r_crosshairs.o r_explosion.o r_explosion.o r_lerpanim.o r_light.o r_modules.o r_sky.o r_sprites.o sbar.o ui.o vid_shared.o view.o wavefile.o
 SERVEROBJECTS= pr_cmds.o pr_edict.o pr_exec.o sv_light.o sv_main.o sv_move.o sv_phys.o sv_user.o
-SHAREDOBJECTS= builddate.o cmd.o collision.o common.o crc.o cvar.o filematch.o host.o host_cmd.o image.o mathlib.o matrixlib.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_dgrm.o net_loop.o net_main.o net_udp.o palette.o portals.o protocol.o quakeio.o sys_linux.o sys_shared.o transform.o world.o wad.o zone.o $(NETOBJECTS) $(SERVEROBJECTS)
+SHAREDOBJECTS= builddate.o cmd.o collision.o common.o crc.o cvar.o filematch.o host.o host_cmd.o image.o mathlib.o matrixlib.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_dgrm.o net_loop.o net_main.o net_master.o net_udp.o palette.o portals.o protocol.o quakeio.o sys_linux.o sys_shared.o transform.o world.o wad.o zone.o $(NETOBJECTS) $(SERVEROBJECTS)
 
 
 #K6/athlon optimizations
diff --git a/menu.c b/menu.c
index fe2097a98d51b7ea81544ca905beb1239eceb4cd..8af1550f3b6b6b1a86238c7b9b50ecb7c2e7743f 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -46,6 +46,7 @@ void M_Menu_Main_f (void);
 void M_Menu_LanConfig_f (void);
 void M_Menu_GameOptions_f (void);
 void M_Menu_Search_f (void);
+void M_Menu_InetSearch_f (void);
 void M_Menu_ServerList_f (void);
 
 void M_Main_Draw (void);
@@ -64,6 +65,7 @@ void M_Main_Draw (void);
 void M_LanConfig_Draw (void);
 void M_GameOptions_Draw (void);
 void M_Search_Draw (void);
+void M_InetSearch_Draw (void);
 void M_ServerList_Draw (void);
 
 void M_Main_Key (int key);
@@ -82,6 +84,7 @@ void M_Main_Key (int key);
 void M_LanConfig_Key (int key);
 void M_GameOptions_Key (int key);
 void M_Search_Key (int key);
+void M_InetSearch_Key (int key);
 void M_ServerList_Key (int key);
 
 qboolean       m_entersound;           // play after drawing a frame, so caching
@@ -853,7 +856,7 @@ void M_MultiPlayer_Draw (void)
 
        if (ipxAvailable || tcpipAvailable)
                return;
-       M_PrintWhite ((320/2) - ((27*8)/2), 148, "No Communications Available");
+       M_PrintWhite ((320/2) - ((27*8)/2), 168, "No Communications Available");
 }
 
 
@@ -2148,8 +2151,8 @@ void M_Quit_Draw (void)
 /* LAN CONFIG MENU */
 
 int            lanConfig_cursor = -1;
-int            lanConfig_cursor_table [] = {72, 92, 124};
-#define NUM_LANCONFIG_CMDS     3
+int            lanConfig_cursor_table [] = {72, 92, 112, 144};
+#define NUM_LANCONFIG_CMDS     4
 
 int    lanConfig_port;
 char   lanConfig_portname[6];
@@ -2213,9 +2216,10 @@ void M_LanConfig_Draw (void)
        if (JoiningGame)
        {
                M_Print (basex, lanConfig_cursor_table[1], "Search for local games...");
-               M_Print (basex, 108, "Join game at:");
-               M_DrawTextBox (basex+8, lanConfig_cursor_table[2]-8, 22, 1);
-               M_Print (basex+16, lanConfig_cursor_table[2], lanConfig_joinname);
+               M_Print (basex, lanConfig_cursor_table[2], "Search for internet games...");
+               M_Print (basex, 128, "Join game at:");
+               M_DrawTextBox (basex+8, lanConfig_cursor_table[3]-8, 22, 1);
+               M_Print (basex+16, lanConfig_cursor_table[3], lanConfig_joinname);
        }
        else
        {
@@ -2228,11 +2232,11 @@ void M_LanConfig_Draw (void)
        if (lanConfig_cursor == 0)
                M_DrawCharacter (basex+9*8 + 8*strlen(lanConfig_portname), lanConfig_cursor_table [0], 10+((int)(realtime*4)&1));
 
-       if (lanConfig_cursor == 2)
-               M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [2], 10+((int)(realtime*4)&1));
+       if (lanConfig_cursor == 3)
+               M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [3], 10+((int)(realtime*4)&1));
 
        if (*m_return_reason)
-               M_PrintWhite (basex, 148, m_return_reason);
+               M_PrintWhite (basex, 168, m_return_reason);
 }
 
 
@@ -2268,18 +2272,21 @@ void M_LanConfig_Key (int key)
 
                M_ConfigureNetSubsystem ();
 
-               if (lanConfig_cursor == 1)
+               if (lanConfig_cursor == 1 || lanConfig_cursor == 2)
                {
                        if (StartingGame)
                        {
                                M_Menu_GameOptions_f ();
                                break;
                        }
-                       M_Menu_Search_f();
+                       if (lanConfig_cursor == 1)
+                               M_Menu_Search_f();
+                       else
+                               M_Menu_InetSearch_f();
                        break;
                }
 
-               if (lanConfig_cursor == 2)
+               if (lanConfig_cursor == 3)
                {
                        m_return_state = m_state;
                        m_return_onerror = true;
@@ -2298,7 +2305,7 @@ void M_LanConfig_Key (int key)
                                lanConfig_portname[strlen(lanConfig_portname)-1] = 0;
                }
 
-               if (lanConfig_cursor == 2)
+               if (lanConfig_cursor == 3)
                {
                        if (strlen(lanConfig_joinname))
                                lanConfig_joinname[strlen(lanConfig_joinname)-1] = 0;
@@ -2309,7 +2316,7 @@ void M_LanConfig_Key (int key)
                if (key < 32 || key > 127)
                        break;
 
-               if (lanConfig_cursor == 2)
+               if (lanConfig_cursor == 3)
                {
                        l = strlen(lanConfig_joinname);
                        if (l < 21)
@@ -2332,7 +2339,7 @@ void M_LanConfig_Key (int key)
                }
        }
 
-       if (StartingGame && lanConfig_cursor == 2)
+       if (StartingGame && lanConfig_cursor == 3)
        {
                if (key == K_UPARROW)
                        lanConfig_cursor = 1;
@@ -2992,6 +2999,63 @@ void M_Search_Key (int key)
 {
 }
 
+//=============================================================================
+/* INTERNET SEARCH MENU */
+
+void M_Menu_InetSearch_f (void)
+{
+       key_dest = key_menu;
+       m_state = m_search;
+       m_entersound = false;
+       slistSilent = true;
+       slistLocal = false;
+       searchComplete = false;
+       NET_InetSlist_f();
+
+}
+
+
+void M_InetSearch_Draw (void)
+{
+       cachepic_t      *p;
+       int x;
+
+       p = Draw_CachePic ("gfx/p_multi.lmp");
+       M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi.lmp");
+       x = (320/2) - ((12*8)/2) + 4;
+       M_DrawTextBox (x-8, 32, 12, 1);
+       M_Print (x, 40, "Searching...");
+
+       if(slistInProgress)
+       {
+               NET_Poll();
+               return;
+       }
+
+       if (! searchComplete)
+       {
+               searchComplete = true;
+               searchCompleteTime = realtime;
+       }
+
+       if (hostCacheCount)
+       {
+               M_Menu_ServerList_f ();
+               return;
+       }
+
+       M_PrintWhite ((320/2) - ((22*8)/2), 64, "No Quake servers found");
+       if ((realtime - searchCompleteTime) < 3.0)
+               return;
+
+       M_Menu_LanConfig_f ();
+}
+
+
+void M_InetSearch_Key (int key)
+{
+}
+
 //=============================================================================
 /* SLIST MENU */
 
@@ -3047,7 +3111,7 @@ void M_ServerList_Draw (void)
        M_DrawCharacter (0, 32 + slist_cursor*8, 12+((int)(realtime*4)&1));
 
        if (*m_return_reason)
-               M_PrintWhite (16, 148, m_return_reason);
+               M_PrintWhite (16, 168, m_return_reason);
 }
 
 
diff --git a/net.h b/net.h
index c111bf0e8ed7f3cbe2e70ba2ad4ddd17e4f8f9a2..55800b04815241b718934519301672e8a7db49bf 100644 (file)
--- a/net.h
+++ b/net.h
@@ -165,6 +165,8 @@ typedef struct
        int             (*CloseSocket) (int socket);
        int             (*Connect) (int socket, struct qsockaddr *addr);
        int             (*CheckNewConnections) (void);
+       int             (*Recv) (qbyte *buf, int len, struct qsockaddr *addr);
+       int                     (*Send) (qbyte *buf, int len, struct qsockaddr *addr);
        int             (*Read) (int socket, qbyte *buf, int len, struct qsockaddr *addr);
        int             (*Write) (int socket, qbyte *buf, int len, struct qsockaddr *addr);
        int             (*Broadcast) (int socket, qbyte *buf, int len);
@@ -189,6 +191,7 @@ typedef struct
        int                     (*Init) (void);
        void            (*Listen) (qboolean state);
        void            (*SearchForHosts) (qboolean xmit);
+       qboolean        (*SearchForInetHosts) (char *master);
        qsocket_t       *(*Connect) (char *host);
        qsocket_t       *(*CheckNewConnections) (void);
        int                     (*QGetMessage) (qsocket_t *sock);
@@ -198,6 +201,7 @@ typedef struct
        qboolean        (*CanSendUnreliableMessage) (qsocket_t *sock);
        void            (*Close) (qsocket_t *sock);
        void            (*Shutdown) (void);
+       void            (*Heartbeat) (char *host);
        int                     controlSock;
 } net_driver_t;
 
@@ -273,6 +277,9 @@ struct qsocket_s    *NET_CheckNewConnections (void);
 struct qsocket_s       *NET_Connect (char *host);
 // called by client to connect to a host.  Returns -1 if not able to
 
+void           NET_Heartbeat (void);
+// Send an heartbeat to the master server(s)
+
 qboolean NET_CanSendMessage (qsocket_t *sock);
 // Returns true or false if the given qsocket can currently accept a
 // message to be transmitted.
@@ -329,6 +336,7 @@ extern      qboolean        slistLocal;
 extern cvar_t hostname;
 
 void NET_Slist_f (void);
+void NET_InetSlist_f (void);
 
 #endif
 
index 17135155f2b982740b1c5ed8bceb211476fc8d37..9b547d8318ee31212d7659110a48f5e5396c9fe4 100644 (file)
--- a/net_bsd.c
+++ b/net_bsd.c
@@ -30,6 +30,7 @@ net_driver_t net_drivers[MAX_NET_DRIVERS] =
        Loop_Init,
        Loop_Listen,
        Loop_SearchForHosts,
+       Loop_SearchForInetHosts,
        Loop_Connect,
        Loop_CheckNewConnections,
        Loop_GetMessage,
@@ -38,7 +39,8 @@ net_driver_t net_drivers[MAX_NET_DRIVERS] =
        Loop_CanSendMessage,
        Loop_CanSendUnreliableMessage,
        Loop_Close,
-       Loop_Shutdown
+       Loop_Shutdown,
+       Loop_Heartbeat
        }
        ,
        {
@@ -47,6 +49,7 @@ net_driver_t net_drivers[MAX_NET_DRIVERS] =
        Datagram_Init,
        Datagram_Listen,
        Datagram_SearchForHosts,
+       Datagram_SearchForInetHosts,
        Datagram_Connect,
        Datagram_CheckNewConnections,
        Datagram_GetMessage,
@@ -55,7 +58,8 @@ net_driver_t net_drivers[MAX_NET_DRIVERS] =
        Datagram_CanSendMessage,
        Datagram_CanSendUnreliableMessage,
        Datagram_Close,
-       Datagram_Shutdown
+       Datagram_Shutdown,
+       Datagram_Heartbeat
        }
 };
 
@@ -76,6 +80,8 @@ net_landriver_t       net_landrivers[MAX_NET_DRIVERS] =
        UDP_CloseSocket,
        UDP_Connect,
        UDP_CheckNewConnections,
+       UDP_Recv,
+       UDP_Send,
        UDP_Read,
        UDP_Write,
        UDP_Broadcast,
index 20f06c58d9f8fd468a83d3c32bff586f5e570954..66ec880da483b1ba4f135ab15934175870b490ba 100644 (file)
@@ -54,6 +54,7 @@ unsigned long inet_addr(const char *cp);
 
 #include "quakedef.h"
 #include "net_dgrm.h"
+#include "net_master.h"
 
 cvar_t cl_port = {CVAR_SAVE, "cl_port", "0"};
 
@@ -847,8 +848,18 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
        MSG_BeginReading ();
        control = BigLong(*((int *)net_message.data));
        MSG_ReadLong();
-       if (control == -1)
+       
+       // Messages starting by 0xFFFFFFFF are master server messages
+       if (control == 0xFFFFFFFF)
+       {
+               int responsesize = Master_HandleMessage();
+               if (responsesize > 0)
+               {
+                       dfunc.Write(acceptsock, net_message.data, responsesize, &clientaddr);
+                       SZ_Clear(&net_message);
+               }
                return NULL;
+       }
        if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
                return NULL;
        if ((control & NETFLAG_LENGTH_MASK) != len)
@@ -860,6 +871,8 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
                if (strcmp(MSG_ReadString(), "QUAKE") != 0)
                        return NULL;
 
+               Con_DPrintf("Datagram_CheckNewConnections: received CCREQ_SERVERINFO, replying.\n");
+
                SZ_Clear(&net_message);
                // save space for the header, filled in later
                MSG_WriteLong(&net_message, 0);
@@ -1077,17 +1090,95 @@ qsocket_t *Datagram_CheckNewConnections (void)
 }
 
 
+static qboolean Datagram_HandleServerInfo (struct qsockaddr *readaddr)
+{
+       struct qsockaddr myaddr;
+       int control;
+       int c, n, i;
+
+       if (net_message.cursize < sizeof(int))
+               return false;
+
+       // don't answer our own query
+       dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
+       //if (dfunc.AddrCompare(readaddr, &myaddr) >= 0)
+       //      return false;
+
+       // is the cache full?
+       if (hostCacheCount == HOSTCACHESIZE)
+               return false;
+
+       MSG_BeginReading ();
+       control = BigLong(*((int *)net_message.data));
+       MSG_ReadLong();
+       if (control == -1)
+               return false;
+       if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+               return false;
+       if ((control & NETFLAG_LENGTH_MASK) != net_message.cursize)
+               return false;
+
+       c = MSG_ReadByte();
+       if (c != CCREP_SERVER_INFO)
+               return false;
+
+       dfunc.GetAddrFromName(MSG_ReadString(), readaddr);
+       // search the cache for this server
+       for (n = 0; n < hostCacheCount; n++)
+               if (dfunc.AddrCompare(readaddr, &hostcache[n].addr) == 0)
+                       break;
+
+       // is it already there?
+       if (n < hostCacheCount)
+               return false;;
+
+       // add it
+       hostCacheCount++;
+       strcpy(hostcache[n].name, MSG_ReadString());
+       strcpy(hostcache[n].map, MSG_ReadString());
+       hostcache[n].users = MSG_ReadByte();
+       hostcache[n].maxusers = MSG_ReadByte();
+       c = MSG_ReadByte();
+       if (c != NET_PROTOCOL_VERSION)
+       {
+               strcpy(hostcache[n].cname, hostcache[n].name);
+               hostcache[n].cname[14] = 0;
+               strcpy(hostcache[n].name, "*");
+               strcat(hostcache[n].name, hostcache[n].cname);
+       }
+       memcpy(&hostcache[n].addr, readaddr, sizeof(struct qsockaddr));
+       hostcache[n].driver = net_driverlevel;
+       hostcache[n].ldriver = net_landriverlevel;
+       strcpy(hostcache[n].cname, dfunc.AddrToString(readaddr));
+
+       // check for a name conflict
+       for (i = 0; i < hostCacheCount; i++)
+       {
+               if (i == n)
+                       continue;
+               if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
+               {
+                       i = strlen(hostcache[n].name);
+                       if (i < 15 && hostcache[n].name[i-1] > '8')
+                       {
+                               hostcache[n].name[i] = '0';
+                               hostcache[n].name[i+1] = 0;
+                       }
+                       else
+                               hostcache[n].name[i-1]++;
+                       i = -1;
+               }
+       }
+
+       return true;
+}
+
+
 static void _Datagram_SearchForHosts (qboolean xmit)
 {
        int             ret;
-       int             n;
-       int             i;
        struct qsockaddr readaddr;
-       struct qsockaddr myaddr;
-       int             control;
-       int             c;
 
-       dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
        if (xmit)
        {
                SZ_Clear(&net_message);
@@ -1103,91 +1194,78 @@ static void _Datagram_SearchForHosts (qboolean xmit)
 
        while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
        {
-               if (ret < sizeof(int))
-                       continue;
                net_message.cursize = ret;
+               Datagram_HandleServerInfo (&readaddr);
+       }
+}
 
-               // don't answer our own query
-               if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
-                       continue;
-
-               // is the cache full?
+void Datagram_SearchForHosts (qboolean xmit)
+{
+       for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
+       {
                if (hostCacheCount == HOSTCACHESIZE)
-                       continue;
-
-               MSG_BeginReading ();
-               control = BigLong(*((int *)net_message.data));
-               MSG_ReadLong();
-               if (control == -1)
-                       continue;
-               if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
-                       continue;
-               if ((control & NETFLAG_LENGTH_MASK) != ret)
-                       continue;
-
-               c = MSG_ReadByte();
-               if (c != CCREP_SERVER_INFO)
-                       continue;
+                       break;
+               if (net_landrivers[net_landriverlevel].initialized)
+                       _Datagram_SearchForHosts (xmit);
+       }
+}
 
-               dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
-               // search the cache for this server
-               for (n = 0; n < hostCacheCount; n++)
-                       if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
-                               break;
 
-               // is it already there?
-               if (n < hostCacheCount)
-                       continue;
+static qboolean _Datagram_SearchForInetHosts (char *master)
+{
+       qboolean result = false;
+       struct qsockaddr masteraddr;
+       struct qsockaddr readaddr;
+       int ret;
 
-               // add it
-               hostCacheCount++;
-               strcpy(hostcache[n].name, MSG_ReadString());
-               strcpy(hostcache[n].map, MSG_ReadString());
-               hostcache[n].users = MSG_ReadByte();
-               hostcache[n].maxusers = MSG_ReadByte();
-               c = MSG_ReadByte();
-               if (c != NET_PROTOCOL_VERSION)
+       if (master)
+       {
+               if (dfunc.GetAddrFromName(master, &masteraddr) != -1)
                {
-                       strcpy(hostcache[n].cname, hostcache[n].name);
-                       hostcache[n].cname[14] = 0;
-                       strcpy(hostcache[n].name, "*");
-                       strcat(hostcache[n].name, hostcache[n].cname);
+                       int portnum = 0;
+                       const char* port = strrchr (master, ':');
+                       if (port)
+                               portnum = atoi (port + 1);
+                       if (!portnum)
+                               portnum = MASTER_PORT;
+                       Con_DPrintf("Datagram_SearchForInetHosts: sending %d byte message to master %s\n", net_message.cursize, master);
+                       dfunc.SetSocketPort (&masteraddr, portnum);
+                       dfunc.Send (net_message.data, net_message.cursize, &masteraddr);
                }
-               memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
-               hostcache[n].driver = net_driverlevel;
-               hostcache[n].ldriver = net_landriverlevel;
-               strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
+       }
 
-               // check for a name conflict
-               for (i = 0; i < hostCacheCount; i++)
-               {
-                       if (i == n)
-                               continue;
-                       if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
-                       {
-                               i = strlen(hostcache[n].name);
-                               if (i < 15 && hostcache[n].name[i-1] > '8')
-                               {
-                                       hostcache[n].name[i] = '0';
-                                       hostcache[n].name[i+1] = 0;
-                               }
-                               else
-                                       hostcache[n].name[i-1]++;
-                               i = -1;
-                       }
-               }
+       while ((ret = dfunc.Recv (net_message.data, net_message.maxsize, &readaddr)) > 0)
+       {
+               net_message.cursize = ret;
+               Con_DPrintf("Datagram_SearchForInetHosts: Recv received %d byte message\n", net_message.cursize);
+               Master_ParseServerList (&dfunc);
        }
+       
+       while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
+       {
+               net_message.cursize = ret;
+               Con_DPrintf("Datagram_SearchForInetHosts: Read received %d byte message\n", net_message.cursize);
+               if (Datagram_HandleServerInfo (&readaddr))
+                       result = true;
+       }
+
+       return result;
 }
 
-void Datagram_SearchForHosts (qboolean xmit)
+
+qboolean Datagram_SearchForInetHosts (char *master)
 {
+       qboolean result = false;
        for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
        {
                if (hostCacheCount == HOSTCACHESIZE)
                        break;
                if (net_landrivers[net_landriverlevel].initialized)
-                       _Datagram_SearchForHosts (xmit);
+                       if (_Datagram_SearchForInetHosts (master))
+                               result = true;
        }
+       
+       return result;
 }
 
 
@@ -1367,3 +1445,29 @@ qsocket_t *Datagram_Connect (char *host)
        return ret;
 }
 
+static void _Datagram_Heartbeat (char *master)
+{
+       struct qsockaddr masteraddr;
+       int portnum;
+       const char* port;
+
+       if (dfunc.GetAddrFromName(master, &masteraddr) == -1)
+               return;
+
+       portnum = 0;
+       port = strrchr (master, ':');
+       if (port)
+               portnum = atoi (port + 1);
+       if (!portnum)
+               portnum = MASTER_PORT;
+       dfunc.SetSocketPort (&masteraddr, portnum);
+
+       dfunc.Send (net_message.data, net_message.cursize, &masteraddr);
+}
+
+void Datagram_Heartbeat (char *master)
+{
+       for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
+               if (net_landrivers[net_landriverlevel].initialized)
+                       _Datagram_Heartbeat (master);
+}
index af4013928ceb81227007445c933ef3daca3d72d7..da3f28bc53effc785498977ff86a1c079ed1875a 100644 (file)
@@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 int                    Datagram_Init (void);
 void           Datagram_Listen (qboolean state);
 void           Datagram_SearchForHosts (qboolean xmit);
+qboolean       Datagram_SearchForInetHosts (char *master);
 qsocket_t      *Datagram_Connect (char *host);
 qsocket_t      *Datagram_CheckNewConnections (void);
 int                    Datagram_GetMessage (qsocket_t *sock);
@@ -34,6 +35,7 @@ qboolean      Datagram_CanSendMessage (qsocket_t *sock);
 qboolean       Datagram_CanSendUnreliableMessage (qsocket_t *sock);
 void           Datagram_Close (qsocket_t *sock);
 void           Datagram_Shutdown (void);
+void           Datagram_Heartbeat (char *master);
 
 #endif
 
index bfb356b5a648997d78ab3a81b1062a1edb04c404..0cd6662e886d9372a1e1489024d97cd7b5f5d599 100644 (file)
@@ -39,6 +39,11 @@ void Loop_Shutdown (void)
 }
 
 
+void Loop_Heartbeat (char *master)
+{
+}
+
+
 void Loop_Listen (qboolean state)
 {
 }
@@ -62,6 +67,12 @@ void Loop_SearchForHosts (qboolean xmit)
 }
 
 
+qboolean Loop_SearchForInetHosts (char *master)
+{
+       return false;
+}
+
+
 qsocket_t *Loop_Connect (char *host)
 {
        if (strcmp(host,"local") != 0)
index 4f248f494c39cffdd32792659f945a479d7ec916..2d62a6c085aab74d73d3c88a013c4f67b3e029d8 100644 (file)
@@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 int                    Loop_Init (void);
 void           Loop_Listen (qboolean state);
 void           Loop_SearchForHosts (qboolean xmit);
+qboolean       Loop_SearchForInetHosts (char *master);
 qsocket_t      *Loop_Connect (char *host);
 qsocket_t      *Loop_CheckNewConnections (void);
 int                    Loop_GetMessage (qsocket_t *sock);
@@ -34,6 +35,7 @@ qboolean      Loop_CanSendMessage (qsocket_t *sock);
 qboolean       Loop_CanSendUnreliableMessage (qsocket_t *sock);
 void           Loop_Close (qsocket_t *sock);
 void           Loop_Shutdown (void);
+void           Loop_Heartbeat (char *master);
 
 #endif
 
index a7137ab3aea7ea599f1d95bc026904033b6b872e..ed2d341d979e636d1328affb0321e6b4b8373dda 100644 (file)
@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // net_main.c
 
 #include "quakedef.h"
+#include "net_master.h"
 
 qsocket_t *net_activeSockets = NULL;
 mempool_t *net_mempool;
@@ -46,6 +47,11 @@ static void Slist_Poll(void);
 PollProcedure  slistSendProcedure = {NULL, 0.0, Slist_Send};
 PollProcedure  slistPollProcedure = {NULL, 0.0, Slist_Poll};
 
+static void InetSlist_Send(void);
+static void InetSlist_Poll(void);
+PollProcedure  inetSlistSendProcedure = {NULL, 0.0, InetSlist_Send};
+PollProcedure  inetSlistPollProcedure = {NULL, 0.0, InetSlist_Poll};
+
 
 sizebuf_t              net_message;
 int                            net_activeconnections = 0;
@@ -220,6 +226,12 @@ static void NET_Port_f (void)
 }
 
 
+static void NET_Heartbeat_f (void)
+{
+       NET_Heartbeat ();
+}
+
+
 static void PrintSlistHeader(void)
 {
        Con_Printf("Server          Map             Users\n");
@@ -273,6 +285,27 @@ void NET_Slist_f (void)
 }
 
 
+void NET_InetSlist_f (void)
+{
+       if (slistInProgress)
+               return;
+
+       if (! slistSilent)
+       {
+               Con_Printf("Looking for Quake servers...\n");
+               PrintSlistHeader();
+       }
+
+       slistInProgress = true;
+       slistStartTime = Sys_DoubleTime();
+
+       SchedulePollProcedure(&inetSlistSendProcedure, 0.0);
+       SchedulePollProcedure(&inetSlistPollProcedure, 0.1);
+
+       hostCacheCount = 0;
+}
+
+
 static void Slist_Send(void)
 {
        for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
@@ -317,6 +350,60 @@ static void Slist_Poll(void)
 }
 
 
+static void InetSlist_Send(void)
+{
+       char* host;
+
+       if (!slistInProgress)
+               return;
+
+       while ((host = Master_BuildGetServers ()) != NULL)
+       {
+               for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
+               {
+                       if (!slistLocal && net_driverlevel == 0)
+                               continue;
+                       if (net_drivers[net_driverlevel].initialized == false)
+                               continue;
+                       dfunc.SearchForInetHosts (host);
+               }
+       }
+
+       if ((Sys_DoubleTime() - slistStartTime) < 3.5)
+               SchedulePollProcedure(&inetSlistSendProcedure, 1.0);
+}
+
+
+static void InetSlist_Poll(void)
+{
+       for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
+       {
+               if (!slistLocal && net_driverlevel == 0)
+                       continue;
+               if (net_drivers[net_driverlevel].initialized == false)
+                       continue;
+               // We stop as soon as we have one answer (FIXME: bad...)
+               if (dfunc.SearchForInetHosts (NULL))
+                       slistInProgress = false;
+       }
+
+       if (! slistSilent)
+               PrintSlist();
+
+       if (slistInProgress && (Sys_DoubleTime() - slistStartTime) < 4.0)
+       {
+               SchedulePollProcedure(&inetSlistPollProcedure, 0.1);
+               return;
+       }
+
+       if (! slistSilent)
+               PrintSlistTrailer();
+       slistInProgress = false;
+       slistSilent = false;
+       slistLocal = true;
+}
+
+
 /*
 ===================
 NET_Connect
@@ -589,6 +676,30 @@ qboolean NET_CanSendMessage (qsocket_t *sock)
 }
 
 
+/*
+====================
+NET_Heartbeat
+
+Send an heartbeat to the master server(s)
+====================
+*/
+void NET_Heartbeat (void)
+{
+       char* host;
+       while ((host = Master_BuildHeartbeat ()) != NULL)
+       {
+               for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
+               {
+                       if (net_drivers[net_driverlevel].initialized == false)
+                               continue;
+                       if (net_driverlevel && listening == false)
+                               continue;
+                       dfunc.Heartbeat (host);
+               }
+       }
+}
+
+
 int NET_SendToAll(sizebuf_t *data, int blocktime)
 {
        double          start;
@@ -704,10 +815,12 @@ void NET_Init (void)
        Cvar_RegisterVariable (&net_messagetimeout);
        Cvar_RegisterVariable (&hostname);
 
-       Cmd_AddCommand ("slist", NET_Slist_f);
+       Cmd_AddCommand ("net_slist", NET_Slist_f);
+       Cmd_AddCommand ("net_inetslist", NET_InetSlist_f);
        Cmd_AddCommand ("listen", NET_Listen_f);
        Cmd_AddCommand ("maxplayers", MaxPlayers_f);
        Cmd_AddCommand ("port", NET_Port_f);
+       Cmd_AddCommand ("heartbeat", NET_Heartbeat_f);
 
        // initialize all the drivers
        for (net_driverlevel=0 ; net_driverlevel<net_numdrivers ; net_driverlevel++)
@@ -725,6 +838,8 @@ void NET_Init (void)
                Con_DPrintf("IPX address %s\n", my_ipx_address);
        if (*my_tcpip_address)
                Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
+
+       Master_Init ();
 }
 
 /*
diff --git a/net_master.c b/net_master.c
new file mode 100644 (file)
index 0000000..8fd7ed8
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+Copyright (C) 2002 Mathieu Olivier
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// net_master.c
+
+#include <malloc.h>
+#include "quakedef.h"
+
+cvar_t sv_masters [] =
+{
+       {CVAR_SAVE, "sv_master1", ""},
+       {CVAR_SAVE, "sv_master2", ""},
+       {CVAR_SAVE, "sv_master3", ""},
+       {CVAR_SAVE, "sv_master4", ""}
+};
+
+
+/*
+====================
+Master_BuildGetServers
+
+Build a getservers request for a master server
+====================
+*/
+char* Master_BuildGetServers (void)
+{
+       static int nextmaster = 0;
+       cvar_t* sv_master;
+       char request [256];
+       
+       if (nextmaster >= sizeof (sv_masters) / sizeof (sv_masters[0]))
+       {
+               nextmaster = 0;
+               return NULL;
+       }
+
+       sv_master = &sv_masters[nextmaster++];
+
+       // No master, no heartbeat
+       if (sv_master->string[0] == '\0')
+       {
+               nextmaster = 0;
+               return NULL;
+       }
+       
+       // Build the heartbeat
+       snprintf (request, sizeof (request), "getservers %s %u empty full\x0A", gamename, NET_PROTOCOL_VERSION);
+       SZ_Clear (&net_message);
+       MSG_WriteLong (&net_message, -1);
+       MSG_WriteString (&net_message, request);
+
+       net_message.cursize--;  // we don't send the trailing '\0'
+
+       return sv_master->string;
+}
+
+
+/*
+====================
+Master_BuildHeartbeat
+
+Build an heartbeat for a master server
+====================
+*/
+char* Master_BuildHeartbeat (void)
+{
+       static int nextmaster = 0;
+       cvar_t* sv_master;
+       
+       if (nextmaster >= sizeof (sv_masters) / sizeof (sv_masters[0]))
+       {
+               nextmaster = 0;
+               return NULL;
+       }
+
+       sv_master = &sv_masters[nextmaster++];
+
+       // No master, no heartbeat
+       if (sv_master->string[0] == '\0')
+       {
+               nextmaster = 0;
+               return NULL;
+       }
+       
+       // Build the heartbeat
+       SZ_Clear (&net_message);
+       MSG_WriteLong (&net_message, -1);
+       MSG_WriteString (&net_message, "heartbeat DarkPlaces\x0A");
+
+       net_message.cursize--;  // we don't send the trailing '\0'
+
+       return sv_master->string;
+}
+
+
+/*
+====================
+Master_HandleMessage
+
+Handle the master server messages
+====================
+*/
+int Master_HandleMessage (void)
+{
+       const char* string = MSG_ReadString ();
+
+       // If it's a "getinfo" request
+       if (!strncmp (string, "getinfo", 7))
+       {
+               char response [512];
+               size_t length;
+
+               length = snprintf (response, sizeof (response), "infoResponse\x0A"
+                                       "\\gamename\\%s\\modname\\%s\\sv_maxclients\\%d"
+                                       "\\clients\\%d\\mapname\\%s\\hostname\\%s\\protocol\\%d",
+                                       gamename, com_modname, svs.maxclients, net_activeconnections,
+                                       sv.name, hostname.string, NET_PROTOCOL_VERSION);
+
+               // Too long to fit into the buffer?
+               if (length >= sizeof (response))
+                       return -1;
+
+               // If there was a challenge in the getinfo message
+               if (string[7] == ' ')
+               {
+                       string += 8;  // skip the header and the space
+
+                       // If the challenge wouldn't fit into the buffer
+                       if (length + 11 + strlen (string) >= sizeof (response))
+                               return -1;
+
+                       sprintf (response + length, "\\challenge\\%s", string);
+               }
+
+               SZ_Clear (&net_message);
+               MSG_WriteLong (&net_message, -1);
+               MSG_WriteString (&net_message, response);
+
+               return net_message.cursize - 1;
+       }
+
+       return 0;
+}
+
+
+/*
+====================
+Master_Init
+
+Initialize the code that handles master server requests and reponses
+====================
+*/
+void Master_Init (void)
+{
+       unsigned int ind;
+       for (ind = 0; ind < sizeof (sv_masters) / sizeof (sv_masters[0]); ind++)
+               Cvar_RegisterVariable (&sv_masters[ind]);
+}
+
+
+/*
+====================
+Master_ParseServerList
+
+Parse getserverResponse messages
+====================
+*/
+void Master_ParseServerList (net_landriver_t* dfunc)
+{
+       int control;
+       qbyte* servers;
+       int ipaddr;
+       struct qsockaddr svaddr;
+       char ipstring [32];
+
+       if (net_message.cursize < sizeof(int))
+               return;
+
+       // is the cache full?
+       if (hostCacheCount == HOSTCACHESIZE)
+               return;
+
+       MSG_BeginReading ();
+       control = BigLong(*((int *)net_message.data));
+       MSG_ReadLong();
+       if (control != -1)
+               return;
+
+       if (strncmp (net_message.data + 4, "getserversResponse\\", 19)) 
+               return;
+
+       // Skip the next 18 bytes
+       MSG_ReadLong(); MSG_ReadLong(); MSG_ReadLong(); MSG_ReadLong();
+       MSG_ReadShort(); MSG_ReadByte();
+
+       servers = alloca (net_message.cursize - 23);
+       memcpy (servers , net_message.data + 23, net_message.cursize - 23);
+
+       // Extract the IP addresses
+       while ((ipaddr = (servers[3] << 24) + (servers[2] << 16) + (servers[1] << 8) + servers[0]) != -1)
+       {
+               int port = (servers[5] << 8) + servers[4];
+
+               if (port == -1 || port == 0)
+                       break;
+
+               port = ((port >> 8) & 0xFF) + ((port & 0xFF) << 8);
+               sprintf (ipstring, "%u.%u.%u.%u:%hu",
+                                       ipaddr & 0xFF, (ipaddr >> 8) & 0xFF,
+                                       (ipaddr >> 16) & 0xFF, ipaddr >> 24,
+                                       port);
+               dfunc->GetAddrFromName (ipstring, &svaddr);
+
+               Con_DPrintf("Requesting info from server %s\n", ipstring);
+               // Send a request at this address
+               SZ_Clear(&net_message);
+               MSG_WriteLong(&net_message, 0);  // save space for the header, filled in later
+               MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
+               MSG_WriteString(&net_message, "QUAKE");
+               MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
+               *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+               dfunc->Write(dfunc->controlSock, net_message.data, net_message.cursize, &svaddr);
+               SZ_Clear(&net_message);
+
+               if (servers[6] != '\\')
+                       break;
+               servers += 7;
+       }
+}
diff --git a/net_master.h b/net_master.h
new file mode 100644 (file)
index 0000000..9325712
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+Copyright (C) 2002 Mathieu Olivier
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// net_master.h
+
+#ifndef NET_MASTER_H
+#define NET_MASTER_H
+
+#define MASTER_PORT 27950
+
+char* Master_BuildGetServers (void);
+char* Master_BuildHeartbeat (void);
+int Master_HandleMessage (void);
+void Master_Init (void);
+void Master_ParseServerList (net_landriver_t* dfunc);
+
+#endif
index b77629807e8359e636b1d335ccea549dccfe6003..2ec8e9ce7bd89598ba450145f26a756ce6387c8c 100644 (file)
--- a/net_udp.c
+++ b/net_udp.c
@@ -244,6 +244,20 @@ int UDP_CheckNewConnections (void)
 
 //=============================================================================
 
+int UDP_Recv (qbyte *buf, int len, struct qsockaddr *addr)
+{
+       return UDP_Read (net_acceptsocket, buf, len, addr);
+}
+
+//=============================================================================
+
+int UDP_Send (qbyte *buf, int len, struct qsockaddr *addr)
+{
+       return UDP_Write (net_acceptsocket, buf, len, addr);
+}
+
+//=============================================================================
+
 int UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr)
 {
        int addrlen = sizeof (struct qsockaddr);
index 06b531bf5984bfa37ef76ea21b1df6400a94d3d3..1210e7217b371f21b6898344f9e67f5edb989f4f 100644 (file)
--- a/net_udp.h
+++ b/net_udp.h
@@ -29,6 +29,8 @@ int  UDP_OpenSocket (int port);
 int  UDP_CloseSocket (int socket);
 int  UDP_Connect (int socket, struct qsockaddr *addr);
 int  UDP_CheckNewConnections (void);
+int  UDP_Recv (qbyte *buf, int len, struct qsockaddr *addr);
+int  UDP_Send (qbyte *buf, int len, struct qsockaddr *addr);
 int  UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr);
 int  UDP_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr);
 int  UDP_Broadcast (int socket, qbyte *buf, int len);
index d34348cdea22433e1b9e3de651721623f75ed5d1..725eef4f5f9347981141a6b9b1fbc63a05f865e3 100644 (file)
--- a/net_win.c
+++ b/net_win.c
@@ -30,6 +30,7 @@ net_driver_t net_drivers[MAX_NET_DRIVERS] =
        Loop_Init,
        Loop_Listen,
        Loop_SearchForHosts,
+       Loop_SearchForInetHosts,
        Loop_Connect,
        Loop_CheckNewConnections,
        Loop_GetMessage,
@@ -47,6 +48,7 @@ net_driver_t net_drivers[MAX_NET_DRIVERS] =
        Datagram_Init,
        Datagram_Listen,
        Datagram_SearchForHosts,
+       Datagram_SearchForInetHosts,
        Datagram_Connect,
        Datagram_CheckNewConnections,
        Datagram_GetMessage,
@@ -78,6 +80,8 @@ net_landriver_t       net_landrivers[MAX_NET_DRIVERS] =
        WINS_CloseSocket,
        WINS_Connect,
        WINS_CheckNewConnections,
+       WINS_Recv,
+       WINS_Send,
        WINS_Read,
        WINS_Write,
        WINS_Broadcast,
@@ -101,6 +105,8 @@ net_landriver_t     net_landrivers[MAX_NET_DRIVERS] =
        WIPX_CloseSocket,
        WIPX_Connect,
        WIPX_CheckNewConnections,
+       WIPX_Recv,
+       WIPX_Send,
        WIPX_Read,
        WIPX_Write,
        WIPX_Broadcast,
index 5a12f52c16d5865b1f40f0d931e269506c6b6f9c..16c1eb7a153339bc6db1abcf941b7f6558d35c93 100644 (file)
@@ -392,6 +392,20 @@ int WINS_CheckNewConnections (void)
 
 //=============================================================================
 
+int WINS_Recv (qbyte *buf, int len, struct qsockaddr *addr)
+{
+       return WINS_Read (net_acceptsocket, buf, len, addr);
+}
+
+//=============================================================================
+
+int WINS_Send (qbyte *buf, int len, struct qsockaddr *addr)
+{
+       return WINS_Write (net_acceptsocket, buf, len, addr);
+}
+
+//=============================================================================
+
 int WINS_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr)
 {
        int addrlen = sizeof (struct qsockaddr);
index a90da5b3ba7e9d99a2a5657e6ee15fd79e049872..7f401ab0616b9c66314d6c22666d6b74d2f88f32 100644 (file)
@@ -29,6 +29,8 @@ int  WINS_OpenSocket (int port);
 int  WINS_CloseSocket (int socket);
 int  WINS_Connect (int socket, struct qsockaddr *addr);
 int  WINS_CheckNewConnections (void);
+int  WINS_Recv (qbyte *buf, int len, struct qsockaddr *addr);
+int  WINS_Send (qbyte *buf, int len, struct qsockaddr *addr);
 int  WINS_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr);
 int  WINS_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr);
 int  WINS_Broadcast (int socket, qbyte *buf, int len);
index f1d2123632372f9cc606835c8aee14689da4a44a..3e62cb4c0a07a1357c297280f9c707dfe45ddf64 100644 (file)
@@ -230,6 +230,20 @@ int WIPX_CheckNewConnections (void)
 
 //=============================================================================
 
+int WIPX_Recv (qbyte *buf, int len, struct qsockaddr *addr)
+{
+       return WIPX_Read (net_acceptsocket, buf, len, addr);
+}
+
+//=============================================================================
+
+int WIPX_Send (qbyte *buf, int len, struct qsockaddr *addr)
+{
+       return WIPX_Write (net_acceptsocket, buf, len, addr);
+}
+
+//=============================================================================
+
 static qbyte packetBuffer[NET_DATAGRAMSIZE + 4];
 
 int WIPX_Read (int handle, qbyte *buf, int len, struct qsockaddr *addr)
index b8caf43675f331b1b0f27ca410522b5add1440c2..120b2ab3460080f6cf43f41bf81172affba07b1a 100644 (file)
@@ -29,6 +29,8 @@ int  WIPX_OpenSocket (int port);
 int  WIPX_CloseSocket (int socket);
 int  WIPX_Connect (int socket, struct qsockaddr *addr);
 int  WIPX_CheckNewConnections (void);
+int  WIPX_Recv (qbyte *buf, int len, struct qsockaddr *addr);
+int  WIPX_Send (qbyte *buf, int len, struct qsockaddr *addr);
 int  WIPX_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr);
 int  WIPX_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr);
 int  WIPX_Broadcast (int socket, qbyte *buf, int len);
index 17f5f5007bb78b5b9c78f41c8d4dd474ea191485..9dd462f3db55fc27c121c9f2517a3a1590a9e45d 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -383,6 +383,7 @@ void SV_CheckForNewClients (void)
                SV_ConnectClient (i);
 
                net_activeconnections++;
+               NET_Heartbeat ();
        }
 }
 
@@ -1842,5 +1843,6 @@ void SV_SpawnServer (const char *server)
                        SV_SendServerinfo (host_client);
 
        Con_DPrintf ("Server spawned.\n");
+       NET_Heartbeat ();
 }