(de)serialisation in server/client goes world_t -> const char *, rather than world_t -> json_t -> const char *

This commit is contained in:
snit 2024-10-10 17:31:07 -05:00
parent 8d5fc464cb
commit 3efa5479f2
5 changed files with 90 additions and 46 deletions

View File

@ -16,29 +16,28 @@ int main(void) {
if (err) goto handle_error; if (err) goto handle_error;
char ibuf[1024] = { 0 }; char ibuf[1024] = { 0 };
char obuf[1024] = { 0 };
// TODO: I skipped out on most error handling here
read(sock, ibuf, 1024); read(sock, ibuf, 1024);
struct json_error_t json_err;
struct json_t *json = json_loads(ibuf, 0, &json_err);
struct world_t world = { 0 }; struct world_t world = { 0 };
world_deserialise(&world, json); err = world_deserialise(&world, ibuf);
if (err != ERR_OK) goto handle_error_sock;
printf("CLIENT: (%zu %zu)\n", world.height, world.width); printf("CLIENT: (%zu %zu) ->", world.height++, world.width ++);
printf(" (%zu %zu)\n", world.height, world.width);
struct json_t *new_json; char obuf[1024] = { 0 };
world_serialise(&world, &new_json); err = world_serialise_buf(&world, obuf, 1024);
if (err != ERR_OK) goto handle_error_sock;
json_dumpb(new_json, obuf, 1024, 0);
write(sock, obuf, 1024); write(sock, obuf, 1024);
close(sock); close(sock);
return ERR_OK; return ERR_OK;
handle_error_sock:
close(sock);
handle_error: handle_error:
printf("ERROR: %s\n", ERROR_STRS[err]); printf("CLIENT ERROR: %s\n", ERROR_STRS[err]);
return err; return err;
} }

View File

@ -22,19 +22,11 @@ struct world_t {
enum error_t world_init(struct world_t *, size_t, size_t); enum error_t world_init(struct world_t *, size_t, size_t);
void world_free(struct world_t *); void world_free(struct world_t *);
// json_t doesn't store the json data itself; the value of the pointer is // world_*_str() allocates a string that the caller must free()
// apparently needed for jansson to use the data, so I need a double pointer // world_*_buf() uses a pre-existing buffer; results are not zero-terminated
// enum error_t world_serialise_str(struct world_t *, char const **);
// TODO enum error_t world_serialise_buf(struct world_t *, char *, size_t);
// Right now, to serialise and deserialise again you have to call: enum error_t world_deserialise(struct world_t *, char const *);
// 1. world_serialise() | world_t -> json_t
// 2. json_dumpX() | json_t -> char *
// 3. json_loadX() | char * -> json_t
// 4. world_deserialise() | json_t -> world_t
//
// Perhaps these two functions should go directly between world_t and char *
enum error_t world_serialise(struct world_t *, struct json_t **);
enum error_t world_deserialise(struct world_t *, struct json_t *);
enum error_t world_register_entity(struct world_t *, char const *, char); enum error_t world_register_entity(struct world_t *, char const *, char);
enum error_t world_place_entity(struct world_t *, size_t, size_t, size_t); enum error_t world_place_entity(struct world_t *, size_t, size_t, size_t);

View File

@ -40,7 +40,7 @@ void world_free(struct world_t *self) {
} }
enum error_t world_serialise(struct world_t *self, struct json_t **json) { static enum error_t serialise(struct world_t *self, struct json_t **json) {
assert(self != NULL); assert(self != NULL);
// TODO: (de)serialise the following: // TODO: (de)serialise the following:
// struct entity_t entities[MAX_ENTITIES]; // struct entity_t entities[MAX_ENTITIES];
@ -57,7 +57,23 @@ enum error_t world_serialise(struct world_t *self, struct json_t **json) {
} }
enum error_t world_deserialise(struct world_t *self, struct json_t *json) { enum error_t world_serialise_str(struct world_t *self, char const **strptr) {
assert(self != NULL);
assert(strptr != NULL);
struct json_t *json;
enum error_t err = serialise(self, &json);
if (err != ERR_OK) return ERR_JSON_SERIALISE;
const char *str = json_dumps(json, 0);
if (str == NULL) return ERR_JSON_SERIALISE;
*strptr = str;
return ERR_OK;
}
static enum error_t deserialise(struct world_t *self, struct json_t *json) {
assert(self != NULL); assert(self != NULL);
assert(json != NULL); assert(json != NULL);
@ -71,6 +87,36 @@ enum error_t world_deserialise(struct world_t *self, struct json_t *json) {
} }
enum error_t world_serialise_buf(struct world_t *self, char *buf, size_t len) {
assert(self != NULL);
assert(buf != NULL);
assert(len > 0);
struct json_t *json;
enum error_t err = serialise(self, &json);
if (err != ERR_OK) return ERR_JSON_SERIALISE;
size_t bytes_written = json_dumpb(json, buf, len, 0);
if (bytes_written == 0) return ERR_JSON_SERIALISE;
return ERR_OK;
}
enum error_t world_deserialise(struct world_t *self, char const *str) {
assert(self != NULL);
assert(str != NULL);
struct json_t *json = json_loads(str, 0, NULL);
if (json == NULL) return ERR_JSON_DESERIALISE;
enum error_t err = deserialise(self, json);
if (err != ERR_OK) return ERR_JSON_DESERIALISE;
return ERR_OK;
}
enum error_t world_register_entity( enum error_t world_register_entity(
struct world_t *self, struct world_t *self,
char const *name, char tile char const *name, char tile

15
run.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/sh
./build.sh
echo "### DAEMON ###"
./build/server/simworld-daemon &
sleep 1
echo "### CLIENT 1 ###"
./build/client/simworld-client
echo "### CLIENT 2 ###"
./build/client/simworld-client
killall simworld-daemon

View File

@ -22,33 +22,25 @@ static void handle_signal(int signal_no) {
} }
#define LOGMSG(options, fmt, ...) \
((options)->daemonise ? \
syslog(LOG_NOTICE, (fmt), __VA_ARGS__) : \
(void)printf((fmt), __VA_ARGS__))
enum error_t game_loop(struct data_t *data) { enum error_t game_loop(struct data_t *data) {
enum error_t err = ERR_OK; enum error_t err = ERR_OK;
char obuf[1024] = { 0 };
char ibuf[1024] = { 0 };
// TODO: I skipped out on most error handling here char obuf[1024] = { 0 };
struct json_t *json; err = world_serialise_buf(&data->world, obuf, 1024);
err = world_serialise(&data->world, &json);
if (err != ERR_OK) return err; if (err != ERR_OK) return err;
json_dumpb(json, obuf, 1024, 0);
write(data->socket_accept, obuf, 1024); write(data->socket_accept, obuf, 1024);
char ibuf[1024] = { 0 };
read(data->socket_accept, ibuf, 1024); read(data->socket_accept, ibuf, 1024);
json = json_loads(ibuf, 0, NULL);
struct world_t returned_world; struct world_t old_world = data->world;
world_deserialise(&returned_world, json); err = world_deserialise(&data->world, ibuf);
LOGMSG(&data->options, "SERVER: (%zu %zu) -> (%zu %zu)\n", if (err != ERR_OK) return ERR_OK;
data->world.height, data->world.width,
returned_world.height, returned_world.width printf("SERVER: (%zu %zu) -> (%zu %zu)\n",
old_world.height, old_world.width,
data->world.height, data->world.width
); );
return ERR_OK; return ERR_OK;
@ -100,6 +92,6 @@ handle_error:
opts_free(&data.options); opts_free(&data.options);
handle_error_pre_opts: handle_error_pre_opts:
printf("ERROR: %s\n", ERROR_STRS[err]); printf("SERVER ERROR: %s\n", ERROR_STRS[err]);
return err; return err;
} }