aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2022-09-20 16:53:48 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2022-09-20 17:34:21 +0200
commit84c834c00023bbb581b9747e17039fd38facdda1 (patch)
treea336659043e5d05aad88c67946a791d8e21fbb8d
parentf42f5f69c8ab7bad09eb2d9a8d5631e1872c41d3 (diff)
Implement net component
-rw-r--r--CMakeLists.txt4
-rw-r--r--README.md4
-rw-r--r--cmake/win9x.cmake1
-rw-r--r--doc/BUILD-win9x.md8
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/net/CMakeLists.txt32
-rw-r--r--src/net/inc/net.h78
-rw-r--r--src/net/privinc/net_private.h30
-rw-r--r--src/net/src/common.c12
-rw-r--r--src/net/src/enet/ipv4.c161
-rw-r--r--src/net/src/net.c111
-rw-r--r--src/net/src/posix/serial.c44
-rw-r--r--src/net/src/ps1/net.c42
-rw-r--r--src/net/src/win9x/serial.c44
14 files changed, 572 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 13efa1c..c2a1339 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,6 +35,10 @@ if(SDL1_2_BUILD)
target_link_libraries(SDL::SDL_mixer INTERFACE SDL::SDL)
endif()
+if(NOT PS1_BUILD)
+ find_package(ENET 1.3 REQUIRED)
+endif()
+
set(cdroot ${CMAKE_BINARY_DIR}/cdimg)
file(MAKE_DIRECTORY ${cdroot})
diff --git a/README.md b/README.md
index b808c01..b8a685e 100644
--- a/README.md
+++ b/README.md
@@ -91,6 +91,7 @@ cd build
SDLDIR=<sdl-prefix> \
SDLMIXERDIR=<sdl_mixer-prefix> \
SDLGFXDIR=<sdl_gfx-prefix> \
+ ENETDIR=<enet-prefix> \
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/win9x-toolchain.cmake
make -j$(nproc --all)
```
@@ -106,6 +107,9 @@ building `SDL_mixer`.
- `SDLGFXDIR` is the path to the cross-compiled version for `SDL_gfx`,
which would correspond to `./configure --prefix=$SDLGFXDIR` used in
building `SDL_gfx`.
+- `ENETDIR` is the path to the cross-compiled version for `enet`,
+which would correspond to `./configure --prefix=$ENETDIR` used in
+building `enet`.
A stripped version of the executable, as well as game assets, will be
located in `build/cdimg`.
diff --git a/cmake/win9x.cmake b/cmake/win9x.cmake
index a4d8f79..0d91520 100644
--- a/cmake/win9x.cmake
+++ b/cmake/win9x.cmake
@@ -6,6 +6,7 @@ add_custom_command(OUTPUT ${cdroot}/${PROJECT_NAME}
add_custom_target(stripped-exe ALL DEPENDS ${cdroot}/${PROJECT_NAME})
target_link_libraries(SDL::SDL INTERFACE gdi32 user32 winmm dxguid)
+target_link_libraries(ENET INTERFACE ws2_32)
add_compile_options(-march=i386)
diff --git a/doc/BUILD-win9x.md b/doc/BUILD-win9x.md
index b8b053f..cb6368d 100644
--- a/doc/BUILD-win9x.md
+++ b/doc/BUILD-win9x.md
@@ -132,3 +132,11 @@ WAVE files, support for other audio formats is not required.
CFLAGS='-ffunction-sections -fdata-sections' \
CC=i386-mingw32-gcc
```
+
+## ENET
+
+```sh
+../enet-1.3.17/configure --prefix=$HOME/enet-1.3.17-win32 \
+ --host=i386-mingw32 CFLAGS='-ffunction-sections -fdata-sections' \
+ CC=i386-mingw32-gcc
+```
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index da04812..7a35715 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -15,6 +15,7 @@ set(components
keyboard
menu
mouse
+ net
pad
peripheral
player
diff --git a/src/net/CMakeLists.txt b/src/net/CMakeLists.txt
new file mode 100644
index 0000000..38cd8df
--- /dev/null
+++ b/src/net/CMakeLists.txt
@@ -0,0 +1,32 @@
+set(src "src/common.c")
+
+if(PS1_BUILD)
+ set(src ${src}
+ "src/ps1/net.c"
+ )
+else()
+ set(src ${src}
+ "src/net.c"
+ "src/enet/ipv4.c"
+ )
+
+ if(WIN9X_BUILD OR ${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows")
+ set(src ${src} "src/win9x/serial.c")
+ else()
+ # Assume POSIX if the command below executes successfully
+ execute_process(COMMAND uname -m RESULT_VARIABLE result OUTPUT_QUIET)
+
+ if(result)
+ message(FATAL_ERROR "Unknown operating system")
+ else()
+ set(src ${src} "src/posix/serial.c")
+ endif()
+ endif()
+
+ set(priv_deps ${priv_deps} util ENET)
+ set(privinc ${privinc} "privinc")
+endif()
+
+add_library(net ${src})
+target_include_directories(net PUBLIC "inc" PRIVATE ${privinc})
+target_link_libraries(net PRIVATE ${priv_deps})
diff --git a/src/net/inc/net.h b/src/net/inc/net.h
new file mode 100644
index 0000000..cdfeb0e
--- /dev/null
+++ b/src/net/inc/net.h
@@ -0,0 +1,78 @@
+#ifndef NET_H
+#define NET_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+enum net_domain
+{
+ NET_DOMAIN_IPV4,
+ NET_DOMAIN_SERIAL
+};
+
+union net_connect
+{
+ struct net_connect_common
+ {
+ enum net_domain domain;
+ void (*on_connected)(void *arg);
+ void (*on_disconnected)(void *arg);
+ void *arg;
+ } common;
+
+ struct net_connect_ipv4
+ {
+ struct net_connect_common common;
+ const char *addr;
+ uint16_t port;
+ } ipv4;
+
+ struct net_connect_serial
+ {
+ struct net_connect_common common;
+ const char *dev;
+ unsigned long baud;
+
+ enum
+ {
+ NET_PARITY_NONE,
+ NET_PARITY_ODD,
+ NET_PARITY_EVEN
+ } parity;
+ } serial;
+};
+
+union net_server
+{
+ struct net_server_common
+ {
+ enum net_domain domain;
+ unsigned max_players;
+ } common;
+
+ struct net_server_ipv4
+ {
+ struct net_server_common common;
+ uint16_t port;
+ } ipv4;
+
+ struct net_server_serial
+ {
+ struct net_server_common common;
+ } serial;
+};
+
+struct net_socket;
+
+int net_init(void);
+void net_deinit(void);
+int net_update(struct net_socket *s);
+
+struct net_socket *net_server(const union net_server *srv);
+struct net_socket *net_connect(const union net_connect *c);
+int net_read(struct net_socket *s, void *buf, size_t n);
+int net_write(struct net_socket *s, const void *buf, size_t n);
+int net_close(struct net_socket *s);
+const char *net_domain_str(enum net_domain d);
+
+#endif /* NET_H */
diff --git a/src/net/privinc/net_private.h b/src/net/privinc/net_private.h
new file mode 100644
index 0000000..53d7cd1
--- /dev/null
+++ b/src/net/privinc/net_private.h
@@ -0,0 +1,30 @@
+#ifndef NET_PRIVATE_H
+#define NET_PRIVATE_H
+
+#include <net.h>
+
+struct net_socket
+{
+ enum net_domain d;
+ struct net_socket_domain *s;
+};
+
+int net_init_ipv4(void);
+void net_deinit_ipv4(void);
+struct net_socket_domain *net_server_ipv4(const union net_server *srv);
+struct net_socket_domain *net_connect_ipv4(const union net_connect *c);
+int net_read_ipv4(struct net_socket_domain *h, void *buf, size_t n);
+int net_write_ipv4(struct net_socket_domain *h, const void *buf, size_t n);
+int net_close_ipv4(struct net_socket_domain *h);
+int net_update_ipv4(struct net_socket_domain *h);
+
+int net_init_serial(void);
+void net_deinit_serial(void);
+struct net_socket_domain *net_server_serial(const union net_server *srv);
+struct net_socket_domain *net_connect_serial(const union net_connect *c);
+int net_read_serial(struct net_socket_domain *h, void *buf, size_t n);
+int net_write_serial(struct net_socket_domain *h, const void *buf, size_t n);
+int net_close_serial(struct net_socket_domain *h);
+int net_update_serial(struct net_socket_domain *h);
+
+#endif /* NET_PRIVATE_H */
diff --git a/src/net/src/common.c b/src/net/src/common.c
new file mode 100644
index 0000000..8e3c386
--- /dev/null
+++ b/src/net/src/common.c
@@ -0,0 +1,12 @@
+#include <net.h>
+
+const char *net_domain_str(const enum net_domain d)
+{
+ static const char *const s[] =
+ {
+ [NET_DOMAIN_IPV4] = "UDP/IPv4",
+ [NET_DOMAIN_SERIAL] = "Serial"
+ };
+
+ return s[d];
+}
diff --git a/src/net/src/enet/ipv4.c b/src/net/src/enet/ipv4.c
new file mode 100644
index 0000000..16786cc
--- /dev/null
+++ b/src/net/src/enet/ipv4.c
@@ -0,0 +1,161 @@
+#include <net.h>
+#include <net_private.h>
+#include <enet/enet.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct net_socket_domain
+{
+ ENetHost *host;
+ ENetPeer *peers;
+ void (*on_connected)(void *arg);
+ void (*on_disconnected)(void *arg);
+ void *arg;
+};
+
+enum
+{
+ CHANNEL,
+ MAX_CHANNELS
+};
+
+struct net_socket_domain *net_connect_ipv4(const union net_connect *const c)
+{
+ struct net_socket_domain *const s = calloc(1, sizeof *s);
+
+ if (!s)
+ goto failure;
+
+ s->on_connected = c->common.on_connected;
+ s->on_disconnected = c->common.on_disconnected;
+ s->arg = c->common.arg;
+ s->host = enet_host_create(NULL, 1, MAX_CHANNELS, 0, 0);
+
+ if (!s->host)
+ {
+ fprintf(stderr, "%s: enet_host_create failed\n", __func__);
+ goto failure;
+ }
+
+ ENetAddress addr;
+
+ if (enet_address_set_host(&addr, c->ipv4.addr))
+ {
+ fprintf(stderr, "%s: enet_address_set_host failed\n", __func__);
+ goto failure;
+ }
+
+ addr.port = c->ipv4.port;
+
+ if (!(s->peers = enet_host_connect(s->host, &addr, MAX_CHANNELS, 0)))
+ {
+ fprintf(stderr, "%s: enet_host_connect failed\n", __func__);
+ goto failure;
+ }
+
+ return s;
+
+failure:
+
+ if (s && s->host)
+ enet_host_destroy(s->host);
+
+ free(s);
+ return NULL;
+}
+
+int net_read_ipv4(struct net_socket_domain *const s, void *const buf,
+ const size_t n)
+{
+ return -1;
+}
+
+int net_write_ipv4(struct net_socket_domain *const s, const void *const buf,
+ const size_t n)
+{
+ return -1;
+}
+
+int net_close_ipv4(struct net_socket_domain *const s)
+{
+ if (s && s->host)
+ enet_host_destroy(s->host);
+
+ free(s);
+ return 0;
+}
+
+int net_update_ipv4(struct net_socket_domain *const s)
+{
+ int res;
+ ENetEvent ev;
+
+ while ((res = enet_host_service(s->host, &ev, 0)) > 0)
+ {
+ switch (ev.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ if (s->on_connected)
+ s->on_connected(s->arg);
+
+ break;
+
+ case ENET_EVENT_TYPE_DISCONNECT:
+ if (s->on_disconnected)
+ s->on_disconnected(s->arg);
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ break;
+
+ case ENET_EVENT_TYPE_NONE:
+ break;
+ }
+ }
+
+ if (res < 0)
+ {
+ fprintf(stderr, "%s: enet_host_service failed\n", __func__);
+ return res;
+ }
+
+ return 0;
+}
+
+struct net_socket_domain *net_server_ipv4(const union net_server *const srv)
+{
+ struct net_socket_domain *const s = calloc(1, sizeof *s);
+
+ if (!s)
+ goto failure;
+
+ const ENetAddress addr =
+ {
+ .port = srv->ipv4.port
+ };
+
+ s->host = enet_host_create(&addr, srv->common.max_players,
+ MAX_CHANNELS, 0, 0);
+
+ if (!s->host)
+ {
+ fprintf(stderr, "%s: enet_host_create failed\n", __func__);
+ goto failure;
+ }
+
+ return s;
+
+failure:
+ free(s);
+ return NULL;
+}
+
+int net_init_ipv4(void)
+{
+ return enet_initialize();
+}
+
+void net_deinit_ipv4(void)
+{
+ enet_deinitialize();
+}
diff --git a/src/net/src/net.c b/src/net/src/net.c
new file mode 100644
index 0000000..32d372a
--- /dev/null
+++ b/src/net/src/net.c
@@ -0,0 +1,111 @@
+#include <net.h>
+#include <net_private.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+struct net_socket *net_connect(const union net_connect *const c)
+{
+ struct net_socket *const s = calloc(1, sizeof *s);
+
+ if (!s)
+ goto failure;
+
+ static struct net_socket_domain *(*const f[])(const union net_connect *) =
+ {
+ [NET_DOMAIN_IPV4] = net_connect_ipv4,
+ [NET_DOMAIN_SERIAL] = net_connect_serial
+ };
+
+ if (!(s->s = f[c->common.domain](c)))
+ goto failure;
+
+ return s;
+
+failure:
+ free(s);
+ return NULL;
+}
+
+int net_read(struct net_socket *const s, void *const buf, const size_t n)
+{
+ static int (*const f[])(struct net_socket_domain *, void *, size_t) =
+ {
+ [NET_DOMAIN_IPV4] = net_read_ipv4,
+ [NET_DOMAIN_SERIAL] = net_read_serial
+ };
+
+ return f[s->d](s->s, buf, n);
+}
+
+int net_write(struct net_socket *const s, const void *const buf, const size_t n)
+{
+ static int (*const f[])(struct net_socket_domain *, const void *, size_t) =
+ {
+ [NET_DOMAIN_IPV4] = net_write_ipv4,
+ [NET_DOMAIN_SERIAL] = net_write_serial
+ };
+
+ return f[s->d](s->s, buf, n);
+}
+
+int net_close(struct net_socket *const s)
+{
+ if (!s)
+ return 0;
+
+ static int (*const f[])(struct net_socket_domain *) =
+ {
+ [NET_DOMAIN_IPV4] = net_close_ipv4,
+ [NET_DOMAIN_SERIAL] = net_close_serial
+ };
+
+ const int res = f[s->d](s->s);
+
+ free(s);
+ return res;
+}
+
+int net_update(struct net_socket *const s)
+{
+ static int (*const f[])(struct net_socket_domain *) =
+ {
+ [NET_DOMAIN_IPV4] = net_update_ipv4,
+ [NET_DOMAIN_SERIAL] = net_update_serial
+ };
+
+ return f[s->d](s->s);
+}
+
+struct net_socket *net_server(const union net_server *const srv)
+{
+ struct net_socket *const s = calloc(1, sizeof *s);
+
+ if (!s)
+ goto failure;
+
+ s->d = srv->common.domain;
+
+ static struct net_socket_domain *(*const f[])(const union net_server *) =
+ {
+ [NET_DOMAIN_IPV4] = net_server_ipv4,
+ [NET_DOMAIN_SERIAL] = net_server_serial
+ };
+
+ if (!(s->s = f[s->d](srv)))
+ goto failure;
+
+failure:
+ net_close(s);
+ return NULL;
+}
+
+int net_init(void)
+{
+ return net_init_ipv4() || net_init_serial();
+}
+
+void net_deinit(void)
+{
+ net_deinit_ipv4();
+ net_deinit_serial();
+}
diff --git a/src/net/src/posix/serial.c b/src/net/src/posix/serial.c
new file mode 100644
index 0000000..46eb2fa
--- /dev/null
+++ b/src/net/src/posix/serial.c
@@ -0,0 +1,44 @@
+#include <net.h>
+#include <net_private.h>
+#include <stddef.h>
+
+int net_read_serial(struct net_socket_domain *const h, void *const buf,
+ const size_t n)
+{
+ return -1;
+}
+
+int net_write_serial(struct net_socket_domain *const h, const void *const buf,
+ const size_t n)
+{
+ return -1;
+}
+
+int net_close_serial(struct net_socket_domain *const h)
+{
+ return -1;
+}
+
+int net_update_serial(struct net_socket_domain *const h)
+{
+ return -1;
+}
+
+struct net_socket_domain *net_connect_serial(const union net_connect *const srv)
+{
+ return NULL;
+}
+
+struct net_socket_domain *net_server_serial(const union net_server *const srv)
+{
+ return NULL;
+}
+
+int net_init_serial(void)
+{
+ return 0;
+}
+
+void net_deinit_serial(void)
+{
+}
diff --git a/src/net/src/ps1/net.c b/src/net/src/ps1/net.c
new file mode 100644
index 0000000..9ddf6f0
--- /dev/null
+++ b/src/net/src/ps1/net.c
@@ -0,0 +1,42 @@
+#include <net.h>
+#include <errno.h>
+#include <stddef.h>
+
+int net_read(struct net_socket *const h, void *const buf, const size_t n)
+{
+ return -1;
+}
+
+int net_write(struct net_socket *const h, const void *const buf, const size_t n)
+{
+ return -1;
+}
+
+int net_close(struct net_socket *const h)
+{
+ return -1;
+}
+
+int net_update(struct net_socket *const h)
+{
+ return -1;
+}
+
+struct net_socket *net_connect(const union net_connect *const c)
+{
+ return NULL;
+}
+
+struct net_socket *net_server(const union net_server *const c)
+{
+ return NULL;
+}
+
+int net_init(void)
+{
+ return -1;
+}
+
+void net_deinit(void)
+{
+}
diff --git a/src/net/src/win9x/serial.c b/src/net/src/win9x/serial.c
new file mode 100644
index 0000000..46eb2fa
--- /dev/null
+++ b/src/net/src/win9x/serial.c
@@ -0,0 +1,44 @@
+#include <net.h>
+#include <net_private.h>
+#include <stddef.h>
+
+int net_read_serial(struct net_socket_domain *const h, void *const buf,
+ const size_t n)
+{
+ return -1;
+}
+
+int net_write_serial(struct net_socket_domain *const h, const void *const buf,
+ const size_t n)
+{
+ return -1;
+}
+
+int net_close_serial(struct net_socket_domain *const h)
+{
+ return -1;
+}
+
+int net_update_serial(struct net_socket_domain *const h)
+{
+ return -1;
+}
+
+struct net_socket_domain *net_connect_serial(const union net_connect *const srv)
+{
+ return NULL;
+}
+
+struct net_socket_domain *net_server_serial(const union net_server *const srv)
+{
+ return NULL;
+}
+
+int net_init_serial(void)
+{
+ return 0;
+}
+
+void net_deinit_serial(void)
+{
+}