diff --git a/common/include/request.h b/common/include/request.h index 8442ab5..e94e624 100644 --- a/common/include/request.h +++ b/common/include/request.h @@ -40,6 +40,7 @@ struct response_body_get_world_data_t { struct response_t { + enum request_type_t type; bool success; void *body; // The body's type depends on the request's type diff --git a/common/include/world.h b/common/include/world.h index 9eb4822..fb313cd 100644 --- a/common/include/world.h +++ b/common/include/world.h @@ -22,11 +22,14 @@ struct world_t { enum error_t world_init(struct world_t *, size_t, size_t); void world_free(struct world_t *); -enum error_t world_serialise_str(struct world_t *, char const **); +enum error_t world_serialise(struct world_t const *, struct json_t **); +enum error_t world_deserialise(struct world_t *, struct json_t *); + +enum error_t world_serialise_str(struct world_t const *, char const **); enum error_t world_deserialise_str(struct world_t *, char const *); // Operates on strings; serialise allocates so make sure to free -enum error_t world_serialise_buf(struct world_t *, char *, size_t); +enum error_t world_serialise_buf(struct world_t const *, char *, size_t); // Operates on buffers; need not be zero-terminated enum error_t world_register_entity(struct world_t *, char const *, char); diff --git a/common/src/request.c b/common/src/request.c index c615d90..5e6af9e 100644 --- a/common/src/request.c +++ b/common/src/request.c @@ -11,6 +11,9 @@ static char const *REQUEST_JSON_FMT = "{si, so}"; static char const *REQUEST_BODY_GET_WORLD_DATA_JSON_FMT = "{sI}"; // Response Format Strings +static char const *RESPONSE_JSON_FMT = "{sb, si, so}"; + +static char const *RESPONSE_BODY_GET_WORLD_DATA_JSON_FMT = "{so}"; static enum error_t request_serialise_body_get_world_data( @@ -44,6 +47,7 @@ static enum error_t request_serialise_body( default: return ERR_JSON_SERIALISE; } + return ERR_OK; } @@ -135,7 +139,7 @@ enum error_t request_serialise_buf( } json_decref(json); - return ERR_OK; +return ERR_OK; } @@ -237,16 +241,233 @@ enum error_t request_deserialise_str(struct request_t *self, char const *str) { } +static enum error_t response_serialise_body_get_world_data( + struct response_body_get_world_data_t const *self, + struct json_t **jsonptr +) { + assert(self != NULL); + assert(jsonptr != NULL); + + struct json_t *json = NULL; + enum error_t err = world_serialise(&self->world, &json); + if (err != ERR_OK) return err; + + *jsonptr = json; + return ERR_OK; +} + + +static enum error_t response_serialise_body( + struct response_t const *self, + struct json_t **jsonptr +) { + assert(self != NULL); + assert(jsonptr != NULL); + + switch (self->type) { + case REQUEST_GET_WORLD_DATA: + return response_serialise_body_get_world_data(self->body, jsonptr); + + default: return ERR_JSON_SERIALISE; + } + + return ERR_OK; +} + + +static enum error_t response_serialise_parts( + struct json_t *body_json, enum request_type_t request_type, bool success, + struct json_t **jsonptr +) { + assert(body_json != NULL); + assert(jsonptr != NULL); + + struct json_t *json = json_pack(RESPONSE_JSON_FMT, + "success", success, + "request-code", request_type, + "response", body_json + ); + + if (json == NULL) return ERR_JSON_SERIALISE; + + *jsonptr = json; + return ERR_OK; +} + + +static enum error_t response_serialise( + struct response_t const *self, + struct json_t **jsonptr +) { + assert(self != NULL); + assert(jsonptr != NULL); + + // Serialise response body + struct json_t *body_json = NULL; + enum error_t err = response_serialise_body(self, &body_json); + if (err != ERR_OK) return err; + + // Serialise full structure + struct json_t *response_json = NULL; + err = response_serialise_parts( + body_json, self->success, self->type, + &response_json + ); + + if (err != ERR_OK) { + json_decref(body_json); + return err; + } + + *jsonptr = response_json; + return ERR_OK; +} + + enum error_t response_serialise_str( struct response_t const *self, char const **strptr -); +) { + assert(self != NULL); + assert(strptr != NULL); + + struct json_t *json = NULL; + enum error_t err = response_serialise(self, &json); + if (err != ERR_OK) return err; + + const char *str = json_dumps(json, 0); + if (str == NULL) { + json_decref(json); + return ERR_JSON_SERIALISE; + } + + json_decref(json); + + *strptr = str; + return ERR_OK; +} enum error_t response_serialise_buf( struct response_t const *self, char *buf, size_t len -); +) { + assert(self != NULL); + assert(buf != NULL); + assert(len > 0); + + struct json_t *json = NULL; + enum error_t err = response_serialise(self, &json); + if (err != ERR_OK) return err; + + size_t bytes_written = json_dumpb(json, buf, len, 0); + if (bytes_written == 0) { + json_decref(json); + return ERR_JSON_SERIALISE; + } + + json_decref(json); + return ERR_OK; +} -enum error_t response_deserialise_str(struct response_t *self, char const *str); +static enum error_t response_deserialise_parts( + struct json_t **body_json, + enum request_type_t *type, + bool *success, + struct json_t *json +) { + assert(body_json != NULL); + assert(type != NULL); + assert(success != NULL); + assert(json != NULL); + + int err = json_unpack(json, RESPONSE_JSON_FMT, + "success", success, + "request-code", type, + "response", body_json + ); + + if (err < 0) return ERR_JSON_DESERIALISE; + return ERR_OK; +} + + +static enum error_t response_deserialise_body_get_world_data( + struct response_body_get_world_data_t *self, + struct json_t *json +) { + assert(self != NULL); + assert(json != NULL); + + enum error_t err = world_deserialise(&self->world, json); + if (err != ERR_OK) return err; + + return ERR_OK; +} + + +static enum error_t response_deserialise_body( + struct response_t *self, + struct json_t *json +) { + assert(self != NULL); + assert(json != NULL); + + switch (self->type) { + case REQUEST_GET_WORLD_DATA: + self->body = malloc(sizeof(struct response_body_get_world_data_t)); + if (self->body == NULL) return ERR_ALLOC; + + return response_deserialise_body_get_world_data(self->body, json); + + default: return ERR_JSON_SERIALISE; + } +} + + +static enum error_t response_deserialise( + struct response_t *self, + struct json_t *json +) { + assert(self != NULL); + assert(json != NULL); + + struct response_t temp_response = { 0 }; + struct json_t *body_json = NULL; + + enum error_t err = response_deserialise_parts( + &body_json, &temp_response.type, &temp_response.success, json + ); + if (err != ERR_OK) return err; + + err = response_deserialise_body(&temp_response, body_json); + if (err != ERR_OK) { + json_decref(body_json); + return err; + } + + *self = temp_response; + return ERR_OK; +} + + +enum error_t response_deserialise_str( + struct response_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 = response_deserialise(self, json); + if (err != ERR_OK) { + json_decref(json); + return err; + } + + json_decref(json); + return ERR_OK; +} diff --git a/common/src/world.c b/common/src/world.c index f53e741..03b6262 100644 --- a/common/src/world.c +++ b/common/src/world.c @@ -104,7 +104,10 @@ static enum error_t world_serialise_parts( } -static enum error_t world_serialise(struct world_t *self, struct json_t **json) { +enum error_t world_serialise( + struct world_t const *self, + struct json_t **json +) { assert(self != NULL); assert(json != NULL); @@ -212,7 +215,7 @@ static enum error_t world_deserialise_entities( } -static enum error_t world_deserialise(struct world_t *self, struct json_t *json) { +enum error_t world_deserialise(struct world_t *self, struct json_t *json) { assert(self != NULL); assert(json != NULL); @@ -256,7 +259,10 @@ error: } -enum error_t world_serialise_str(struct world_t *self, char const **strptr) { +enum error_t world_serialise_str( + struct world_t const *self, + char const **strptr +) { assert(self != NULL); assert(strptr != NULL); @@ -277,7 +283,10 @@ enum error_t world_serialise_str(struct world_t *self, char const **strptr) { } -enum error_t world_serialise_buf(struct world_t *self, char *buf, size_t len) { +enum error_t world_serialise_buf( + struct world_t const *self, + char *buf, size_t len +) { assert(self != NULL); assert(buf != NULL); assert(len > 0); diff --git a/server/src/main.c b/server/src/main.c index 4afabff..3f0d3f9 100644 --- a/server/src/main.c +++ b/server/src/main.c @@ -27,25 +27,30 @@ enum error_t game_loop(struct data_t *data) { enum error_t err = ERR_OK; // TEMP - struct request_body_get_world_data_t request_body = { 69 }; - struct request_t request = { REQUEST_GET_WORLD_DATA, &request_body }; + struct response_body_get_world_data_t response_body = { data->world }; + struct response_t response = { true, REQUEST_GET_WORLD_DATA, &response_body }; - char const *request_json_str = NULL; - err = request_serialise_str(&request, &request_json_str); + char const *response_json_str = NULL; + err = response_serialise_str(&response, &response_json_str); if (err) return err; - printf("serialised request: %s\n", request_json_str); + printf("serialised response: %s\n", response_json_str); - struct request_t request2 = { 0 }; - err = request_deserialise_str(&request2, request_json_str); + struct response_t response2 = { 0 }; + err = response_deserialise_str(&response2, response_json_str); if (err) return err; - struct request_body_get_world_data_t *request2_body = request2.body; - printf("deserialised request: (%d, %zu)\n", - request2.type, - request2_body->world_id + struct response_body_get_world_data_t *response2_body = response2.body; + + char const *world_json_str = NULL; + err = world_serialise_str(&response2_body->world, &world_json_str); + if (err) return err; + printf("deserialised response: (%d, %d, %s\n", + response2.success, + response2.type, + world_json_str ); - free((void *)request_json_str); + free((void *)response_json_str); // TEMP