This is a quick draft for some better and sane network primitives. One
step toward better network code? Your opinion most welcome.
(Compiles but not tested yet. I cannot test it properly before adding
it (since I need another host to test against), and I'm not adding it
before I see some thumbs up.)
- Per
Index: src/network.c
===================================================================
--- src/network.c (revision 0)
+++ src/network.c (revision 0)
@@ -0,0 +1,74 @@
+/*
+ This file is part of Warzone 2100.
+ Copyright (C) 1999-2004 Eidos Interactive
+ Copyright (C) 2005-2007 Warzone Resurrection Project
+
+ Warzone 2100 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.
+
+ Warzone 2100 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 Warzone 2100; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/* Look at header file for documentation of interface */
+
+#include "network.h"
+
+/* globals - needed for inlining functions from header */
+NETMSG net_msg;
+enum net_direction_enum net_direction;
+
+bool net_string(char *value, uint16_t *length, uint16_t maxlength)
+{
+ uint16_t *store_length = (uint16_t *)&net_msg.body[net_msg.size];
+ char *store = &net_msg.body[net_msg.size + sizeof(uint16_t)];
+ size_t size;
+
+ // check length for size field before accessing it
+ if (sizeof(uint16_t) + net_msg.size > MaxMsgSize || !net_msg.status)
+ {
+ net_msg.status = FALSE;
+ return FALSE;
+ }
+ size = sizeof(char) * *store_length + sizeof(uint16_t);
+ // now check length for both fields
+ if (size + net_msg.size > MaxMsgSize)
+ {
+ net_msg.status = FALSE;
+ return FALSE;
+ }
+ assert(maxlength + net_msg.size + sizeof(uint16_t) <= MaxMsgSize);
+ if (net_direction == NET_WRITE)
+ {
+ assert(*length < maxlength);
+ assert(strnlen(value, maxlength) < *length);
+ *store_length = *length;
+ memcpy(store, value, *length);
+ } else {
+ *length = *store_length;
+ if (*length > maxlength)
+ {
+ debug(LOG_ERROR, "Packet string longer (%lu) than max size of %lu",
+ (unsigned long)*length, (unsigned long)maxlength);
+ net_msg.status = FALSE;
+ return FALSE;
+ }
+ if (strnlen(store, *length) == *length)
+ {
+ debug(LOG_ERROR, "Packet string has no zero termination!");
+ net_msg.status = FALSE;
+ return FALSE;
+ }
+ memcpy(value, store, *length);
+ }
+ net_msg.size += size;
+ return TRUE;
+}
Index: src/network.h
===================================================================
--- src/network.h (revision 0)
+++ src/network.h (revision 0)
@@ -0,0 +1,145 @@
+/*
+ This file is part of Warzone 2100.
+ Copyright (C) 1999-2004 Eidos Interactive
+ Copyright (C) 2005-2007 Warzone Resurrection Project
+
+ Warzone 2100 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.
+
+ Warzone 2100 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 Warzone 2100; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _network_h
+#define _network_h
+
+#include <arpa/inet.h>
+
+#include "lib/framework/frame.h"
+#include "statsdef.h"
+#include "base.h"
+#include "droiddef.h"
+#include "structuredef.h"
+#include "featuredef.h"
+#include "functiondef.h"
+#include "multiplay.h"
+#include "lib/netplay/netplay.h"
+
+/*** The new network API ***/
+
+enum net_direction_enum {
+ NET_READ, NET_WRITE, NET_INVALID
+};
+
+/*
+ This API is inspired by OpenGL and XDR. You use the same function
+ to both read and write, just with different binding (begin parameter).
+
+ These are the functions to use:
+ -------------------------------
+
+ net_begin(enum_direction_enum);
+
+ // pass a pointer to the value you wish to send or receive
+ net_uint8_t(uint8_t*);
+ net_uint16_t(uint16_t*);
+ net_uint32_t(uint32_t*);
+ net_uint64_t(uint64_t*);
+ net_int8_t(int8_t*);
+ net_int16_t(int16_t*);
+ net_int32_t(int32_t*);
+ net_int64_t(int64_t*);
+
+ // pass a pointer to the reference value (ID) of the object
+ // you wish to send or receive, then a pointer to the pointer
+ // of the object itself
+ net_object(uint32_t*, BASE_OBJECT**);
+
+ // send a string, pass the string and a pointer to its length, then
+ // the maximum length this field could ever (safely) have
+ net_string(char*, uint16_t*, uint16_t);
+
+ net_end();
+*/
+
+
+/*** Implementation follows ***/
+
+// these are private members - hands off!
+extern NETMSG net_msg;
+extern enum net_direction_enum net_direction;
+
+static inline void net_begin(enum net_direction_enum direction)
+{
+ net_direction = direction;
+ net_msg.size = 0;
+ net_msg.status = TRUE;
+}
+
+static inline void net_end(void)
+{
+ net_direction = NET_INVALID;
+}
+
+/* General template for most common send/receive functions. Or what you
+ * have to do when you do not use C++. Yes, I know. */
+#define NETFUNCDEF(valtype, hostswap, netswap) \
+ static inline bool net_ ## valtype (valtype *value) \
+ { \
+ valtype *store = (valtype *)&net_msg.body[net_msg.size]; \
+ const int size = sizeof(valtype); \
+ \
+ if (size + net_msg.size > MaxMsgSize || !net_msg.status) \
+ { \
+ net_msg.status = FALSE; \
+ return FALSE; \
+ } \
+ if (net_direction == NET_WRITE) \
+ { \
+ *store = netswap(*value); \
+ } else { \
+ *value = hostswap(*store); \
+ } \
+ net_msg.size += size; \
+ return TRUE; \
+ }
+NETFUNCDEF(uint8_t, , )
+NETFUNCDEF(uint16_t, htons, ntohs)
+NETFUNCDEF(uint32_t, htonl, ntohl)
+NETFUNCDEF(int8_t, , )
+NETFUNCDEF(int16_t, htons, ntohs)
+NETFUNCDEF(int32_t, htonl, ntohl)
+
+/* Strings are sent prefixed with an uint16_t giving its actual length. The
+ * string must be null terminated. This one is too long to be inline. */
+bool net_string(char *value, uint16_t *length, uint16_t maxlength);
+
+static inline bool net_id(uint32_t *value, BASE_OBJECT **psObj)
+{
+ uint32_t *store = (uint32_t *)&net_msg.body[net_msg.size];
+ const int size = sizeof(uint32_t);
+
+ if (size + net_msg.size > MaxMsgSize || !net_msg.status)
+ {
+ net_msg.status = FALSE;
+ return FALSE;
+ }
+ if (net_direction == NET_WRITE)
+ {
+ *store = *value;
+ } else {
+ *psObj = IdToPointer(*store, ANYPLAYER);
+ }
+ net_msg.size += size;
+ return TRUE;
+}
+
+#endif
Index: src/Makefile.am
===================================================================
--- src/Makefile.am (revision 1604)
+++ src/Makefile.am (working copy)
@@ -28,7 +28,7 @@
researchdef.h resource.h scores.h scriptai.h scriptcb.h scriptextern.h scriptfuncs.h \
scriptobj.h scripttabs.h scriptvals.h selection.h seqdisp.h stats.h statsdef.h \
structure.h structuredef.h target.h text.h texture.h transporter.h visibility.h \
- warcam.h warzoneconfig.h weapons.h winmain.h wrappers.h
+ warcam.h warzoneconfig.h weapons.h winmain.h wrappers.h network.h
warzone2100_SOURCES = scriptvals_parser.tab.c scriptvals_lexer.lex.c \
level_lexer.lex.c ai.c aiexperience.c astar.c action.c advvis.c atmos.c bridge.c \
@@ -46,7 +46,7 @@
bucket3d.c clparse.c configuration.c csnap.c display3d.c drive.c function.c game.c \
ingameop.c keyedit.c loadsave.c mission.c multigifts.c multijoin.c multilimit.c \
multiplay.c multistruct.c oprint.c power.c projectile.c seqdisp.c structure.c \
- target.c warzoneconfig.c
+ target.c warzoneconfig.c network.c
warzone2100_LDADD = $(top_builddir)/lib/widget/libwidget.a \
$(top_builddir)/lib/sound/libsound.a $(top_builddir)/lib/sequence/libsequence.a \
Index: src/multiplay.c
===================================================================
--- src/multiplay.c (revision 1604)
+++ src/multiplay.c (working copy)
@@ -68,6 +68,8 @@
#include "multistat.h"
#include "multigifts.h" // gifts and alliances.
+#include "network.h"
+
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// globals.
Index: src/Makefile.raw
===================================================================
--- src/Makefile.raw (revision 1604)
+++ src/Makefile.raw (working copy)
@@ -2,6 +2,7 @@
include $(MAKERULES)/configure.mk
SRC=ai.c \
+ network.c \
aiexperience.c \
astar.c \
action.c \
Index: lib/netplay/netplay.h
===================================================================
--- lib/netplay/netplay.h (revision 1604)
+++ lib/netplay/netplay.h (working copy)
@@ -67,7 +67,7 @@
uint8_t paddedBytes; // numberofbytes appended for encryption
uint8_t type; // type of packet
uint8_t destination; // player to send to, or NET_ALL_PLAYERS
- uint16_t counter; // where in body we are currently
+ bool status; // whether packet is compiled successfully
char body[MaxMsgSize];
} NETMSG;
@@ -112,7 +112,7 @@
uint32_t bCaptureInUse; // true if someone is speaking.
uint32_t bAllowCaptureRecord; // true if speech can be recorded.
uint32_t bAllowCapturePlay; // true if speech can be played.
-} NETPLAY, *LPNETPLAY;
+} NETPLAY;
// ////////////////////////////////////////////////////////////////////////
// variables
_______________________________________________
Warzone-dev mailing list
[email protected]
https://mail.gna.org/listinfo/warzone-dev