This commit is contained in:
Nishi 2025-12-20 12:11:57 +09:00
commit 8e82909923
Signed by: nishi
GPG key ID: 27EF69B208EB9343
9 changed files with 180 additions and 19 deletions

View file

@ -9,10 +9,10 @@ add_subdirectory(external/libfishsoup)
add_subdirectory(external/milsko)
add_subdirectory(external/glad)
file(GLOB SERVER_SRC server/*.c)
file(GLOB CLIENT_SRC client/*.c)
file(GLOB SERVER_SRC server/*.c src/*.c)
file(GLOB CLIENT_SRC client/*.c src/*.c)
add_executable(af_server ${SERVER_SRC})
add_executable(af_server ${SERVER_SRC} external/stb/stb_ds.c)
add_executable(af_client ${CLIENT_SRC} external/stb/stb_image.c)
add_executable(af_dumpfont tools/af_dumpfont.c external/stb/stb_image_write.c)

View file

@ -2,16 +2,63 @@
static fishsoup_client_t* client = NULL;
enum OPAQUE_STATES {
OPAQUE_WAITING_HELLO = 0,
OPAQUE_SENT_JOIN
};
typedef struct opaque {
char username[256];
int state;
} opaque_t;
static void net_return(MwWidget handle, void* user, void* client) {
scene_change(AF_SCENE_MAIN);
}
static void on_packet(fishsoup_client_t* client, fishsoup_packet_t* pkt) {
static void on_packet(fishsoup_client_t* self, fishsoup_packet_t* pkt) {
opaque_t* o = self->user;
if(pkt->header.type == AF_PACKET_HELLO && pkt->header.length == sizeof(af_packet_hello_t) && o->state == OPAQUE_WAITING_HELLO) {
af_packet_hello_t* p_hello = pkt->data;
unsigned char mj, mi, pt;
af_common_version(&mj, &mi, &pt);
af_common_log_info("HELLO packet: Server version %hhu.%hhu.%hhu\n", p_hello->major, p_hello->minor, p_hello->patch);
if(mj == p_hello->major && mi >= p_hello->minor && (mi == p_hello->minor ? (pt >= p_hello->patch) : (1))) {
fishsoup_packet_t p;
af_packet_join_t p_join;
af_common_log_info("Server version is compatible with this client\n");
p.header.type = AF_PACKET_JOIN;
p.header.length = sizeof(p_join);
p.data = &p_join;
memcpy(p_join.username, o->username, 256);
fishsoup_packet_send(self->fd, &p);
o->state = OPAQUE_SENT_JOIN;
return;
}
af_common_log_info("Server version is incompatible with this client\n");
MwAddUserHandler(ui_message("Server version is incompatible with this client"), MwNactivateHandler, net_return, NULL);
fishsoup_client_destroy(self);
client = NULL;
}
}
static void on_disconnect(fishsoup_client_t* self) {
free(self->user);
}
void net_connect(const char* username, const char* hostname, int port) {
fishsoup_packet_t pkt;
af_packet_join_t join;
opaque_t* o;
scene_change(AF_SCENE_CONNECTING);
client = fishsoup_client(hostname, port == 0 ? AF_DEFAULT_PORT : port);
@ -20,20 +67,20 @@ void net_connect(const char* username, const char* hostname, int port) {
return;
}
pkt.header.type = AF_PACKET_JOIN;
pkt.header.length = sizeof(join);
pkt.data = &join;
o = client->user = malloc(sizeof(opaque_t));
o->state = OPAQUE_WAITING_HELLO;
memset(o->username, 0, 256);
memcpy(o->username, username, strlen(username));
fishsoup_client_on_packet(client, on_packet);
fishsoup_packet_send(client->fd, &pkt);
fishsoup_client_on_disconnect(client, on_disconnect);
}
void net_poll(void) {
int ret;
if(client == NULL) return;
while((ret = fishsoup_client_poll(client)) > 0);
while(client != NULL && (ret = fishsoup_client_poll(client)) > 0);
if(ret < 0) {
MwAddUserHandler(ui_message("Connection destroyed"), MwNactivateHandler, net_return, NULL);
fishsoup_client_destroy(client);

View file

@ -1,2 +1,2 @@
#!/bin/sh
clang-format --verbose -i `find include server client tools -name "*.c" -or -name "*.h"`
clang-format --verbose -i `find include server client tools src -name "*.c" -or -name "*.h"`

View file

@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <fishsoup.h>
@ -22,13 +23,36 @@
#define AF_COPYRIGHT "Copyright (C) 2025 Fishsoup"
enum AF_USER_PACKETS {
AF_PACKET_JOIN = FISHSOUP_PACKET_USER
AF_PACKET_HELLO = FISHSOUP_PACKET_USER,
AF_PACKET_OK,
AF_PACKET_ERROR,
AF_PACKET_JOIN
};
#pragma pack(1)
typedef struct af_packet_hello {
unsigned char major;
unsigned char minor;
unsigned char patch;
} af_packet_hello_t;
typedef struct af_packet_ok {
char reason[256];
} af_packet_ok_t;
typedef struct af_packet_error {
char reason[256];
} af_packet_error_t;
typedef struct af_packet_join {
char name[256];
char username[256];
} af_packet_join_t;
#pragma pack()
/* version.c */
void af_common_version(unsigned char* v_major, unsigned char* v_minor, unsigned char* v_patch);
/* log.c */
void af_common_log_info(const char* fmt, ...);
#endif

View file

@ -1,4 +1,8 @@
#ifndef __AF_SERVER_H__
#define __AF_SERVER_H__
/* net.c */
void net_start(int port);
void net_loop(void);
#endif

View file

@ -1,10 +1,9 @@
#include <af_common.h>
int main(int argc, char** argv) {
fishsoup_server_t* server;
int port = 0;
int port = 0;
server = fishsoup_server(port == 0 ? AF_DEFAULT_PORT : port);
net_start(port);
fishsoup_server_loop(server);
net_loop();
}

62
server/net.c Normal file
View file

@ -0,0 +1,62 @@
#include <af_common.h>
static fishsoup_server_t* server;
typedef struct opaque {
char username[256 + 1];
} opaque_t;
static void on_packet(fishsoup_client_t* self, fishsoup_packet_t* pkt) {
opaque_t* o = self->user;
if(pkt->header.type == AF_PACKET_JOIN && pkt->header.length == sizeof(af_packet_join_t)) {
af_packet_join_t* p_join = pkt->data;
o->username[256] = 0;
memcpy(o->username, p_join->username, 256);
af_common_log_info("Client %d: JOIN packet: Username \"%s\"\n", self->fd, o->username);
}
}
static void on_disconnect(fishsoup_client_t* self) {
free(self->user);
af_common_log_info("Client %d: Disconnected\n", self->fd);
}
static void on_client(fishsoup_server_t* self, fishsoup_client_t* client) {
opaque_t* o;
fishsoup_packet_t pkt;
af_packet_hello_t hello;
af_common_log_info("Client %d: Connected\n", client->fd);
o = client->user = malloc(sizeof(opaque_t));
o->username[0] = 0;
fishsoup_client_on_disconnect(client, on_disconnect);
fishsoup_client_on_packet(client, on_packet);
pkt.header.type = AF_PACKET_HELLO;
pkt.header.length = sizeof(hello);
pkt.data = &hello;
af_common_version(&hello.major, &hello.minor, &hello.patch);
fishsoup_packet_send(client->fd, &pkt);
}
void net_start(int port) {
if(port == 0) port = AF_DEFAULT_PORT;
if((server = fishsoup_server(port)) == NULL) return;
fishsoup_server_on_client(server, on_client);
}
void net_loop(void) {
if(server == NULL) return;
fishsoup_server_loop(server);
}

14
src/log.c Normal file
View file

@ -0,0 +1,14 @@
#include <af_common.h>
static void af_common_log(const char* type, const char* fmt, va_list va) {
printf("[%.4s] ", type);
vprintf(fmt, va);
}
void af_common_log_info(const char* fmt, ...) {
va_list va;
va_start(va, fmt);
af_common_log("INFO", fmt, va);
va_end(va);
}

11
src/version.c Normal file
View file

@ -0,0 +1,11 @@
#include <af_common.h>
void af_common_version(unsigned char* v_major, unsigned char* v_minor, unsigned char* v_patch) {
char* mj = AF_VERSION;
char* mi = strchr(mj, '.') + 1;
char* pt = strchr(mi, '.') + 1;
*v_major = atoi(mj);
*v_minor = atoi(mi);
*v_patch = atoi(pt);
}