Implement net component

This commit is contained in:
Xavier Del Campo Romero 2022-09-20 16:53:48 +02:00
parent f42f5f69c8
commit 84c834c000
14 changed files with 572 additions and 0 deletions

View File

@ -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})

View File

@ -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`.

View File

@ -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)

View File

@ -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
```

View File

@ -15,6 +15,7 @@ set(components
keyboard
menu
mouse
net
pad
peripheral
player

32
src/net/CMakeLists.txt Normal file
View File

@ -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})

78
src/net/inc/net.h Normal file
View File

@ -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 */

View File

@ -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 */

12
src/net/src/common.c Normal file
View File

@ -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];
}

161
src/net/src/enet/ipv4.c Normal file
View File

@ -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();
}

111
src/net/src/net.c Normal file
View File

@ -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();
}

View File

@ -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)
{
}

42
src/net/src/ps1/net.c Normal file
View File

@ -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)
{
}

View File

@ -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)
{
}