From b4afa06e383325f4a0c751a64ca896d769db07a8 Mon Sep 17 00:00:00 2001 From: Trumeet Date: Wed, 20 Jul 2022 18:12:22 -0700 Subject: libac: First Commit --- client/libacron/README.md | 199 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 client/libacron/README.md (limited to 'client/libacron/README.md') diff --git a/client/libacron/README.md b/client/libacron/README.md new file mode 100644 index 0000000..11d7663 --- /dev/null +++ b/client/libacron/README.md @@ -0,0 +1,199 @@ +# `libac`: Acron Client Library + +A client library written in C, +based on [json-c](https://github.com/json-c/json-c) and [wic](https://github.com/cjhdev/wic). + +## Building + +Requirements: + +* `json-c` installed and using PkgConfig +* Git +* CMake +* A C11 or higher C compiler +* Connectivity to this git repository and `github.com` + +To build on Unix: + +```shell +git clone https://git.yuuta.moe/Minecraft/acron.git +cd acron +git submodule update --init +cd client/libacron/ +mkdir build +cd build +cmake -DCMAKE_BUILD_TYPE=Release .. +make +``` + +The shared library will be at `libac.so`. + +The distributable headers are at `client/libacron/include/`. + +To make debug builds, use the Debug build type. Debug builds will have ASAN enabled. + +## Usage + +All functions begin with `ac_`. Include `libac.h`. + + +### Thread Safety + +This library is single-threaded, meaning that all functions should be called on a +dedicated thread. However, user may initialize the library on multiple threads and call +the functions on different threads without interfering each other. + +### Error Handling + +All error codes are at `common.h`. `AC_E_*` are library errors (generated by library routines); +`AC_ER_*` are remote errors (generated by the server), and you should match them with `ac_response_error.code`. + +All libac functions return an integer value of the error code. `AC_E_OK(0)` indicates successful operation. + +Any library function calls not following the document will return `AC_E_INVALID_REQUEST`. + +### Struct Inheritance + +All libac exported structs have a `uint8_t type` as its first member. It indicates the type of the object. +The type ID is globally unique and stable across upgrades. + +Internally, the type is an unsigned 8-bit integer, with the first two bits indicating whether it is +an event, a response, or a request. The remaining 6 bits differentiates the type with others. + +Library users usually do not need to care about the internal assignment of type IDs. Every exported struct +have its ID defined in the corresponding headers (e.g. `AC_RESPONSE_OK`). Macros like `AC_IS_EVENT` is also +available (from `ids.h`). + +Thus, the base definition of all libac structs is: + +```c +/* ids.h */ +typedef struct ac_obj { + uint8_t type; +} ac_obj_t; +``` + +are classified in three types: + +* Event: Server-initiated events. Do not have IDs. Base definition: `ac_event_t`. +```c +/* events.h */ +typedef struct ac_event { + uint8_t type; +} ac_event_t; +``` +* Request: Program-allocated requests. Have a program-assigned ID. Base definition: `ac_request_t`. +```c +/* requests.h */ +typedef struct ac_request { + uint8_t type; + int id; +} ac_request_t; +``` +* Response: Responses to requests. Have the same ID as the request. Base definition: `ac_response_t`. +```c +/* requests.h */ +typedef struct ac_response { + uint8_t type; + int id; +} ac_response_t; +``` + +### Struct Memory Management + +For requests only, it is the program's responsibility to allocate them (on whether stack or heap) and +assign the correct type, so libac can recognize them. The program should also free the request after making +`ac_request()` calls, as libac will not modify the request object: + +```c +int list(void *connection) { + /* Allocated on the stack: Freed upon return, not by libac. */ + ac_request_cmd cmd = { + .type = AC_REQUEST_CMD, + .id = 114514, + .config = NULL, + .cmd = "list" + }; + int r = ac_request(connection, (ac_request_t *) &cmd); + /* cmd is freed. */ + return r; +} +``` + +For events and responses, libac will allocate them internally, and the program should free them using +`ac_obj_free(ac_obj_t)` function. + +### Initialization + +To initialize the library on the current thread, call: `ac_init()`: + +```c +int main(void) { + libac_config_t config = { + .out = NULL, /* Error output stream. NULL to disable any error logging. */ + .tok = NULL + } + int r = ac_init(&config); + if (r) return r; +} +``` + +When finished using libac on the thread, call `ac_free()`. + +Any function call without `ac_init()` first will return `AC_E_NOT_INITIALIZED`. + +### Making Connections + +To connect to a server on the current thread, use `ac_connect()`. +It will output a `void *` opaque pointer referencing to the connection. Programs should +pass this pointer as-is when making connections or disconnecting. + +Every thread can have multiple connections simultaneously. + +```c +void *connection = NULL; +int r; +ac_connection_parameters_t args = { + .url = "ws://localhost:25575/ws?id=1&token=123" +}; +if ((r = ac_connect(args, &connection))) { + return r; +} +/* Listen or make requests. */ +``` + +Then, the program can listen for responses or events: + +```c +ac_obj_t *obj = NULL; +while (!interrupted || !(r = ac_receive(connection, &obj))) { + /* The obj is now referencing to a library allocated event or response. */ + /* Do things with the event or response. */ + ac_obj_free(obj); +} +``` + +The program can make requests using `ac_request()`. ~~This function can +be called from any thread (not specific to the listening one), but any thread +calling this function must also call `ac_init()` first.~~ **On the roadmap.** + +Finally, when done, call `ac_disconnect()`. It will close the socket and free the +`connection` parameter. The `connection` pointer after the method call is undefined. + +> **Notes**: +> +> Only `ws://` is supported at this time. `wss://` support is +> on the roadmap. + + +Read more: `acronc/main.c` example client. + +## Roadmap + +* Make unit tests +* SSL support +* Calling `ac_request()` from any thread + +## License + +The libac library is licensed under LGPL-2.1-only. Other parts of Acron is still licensed under GPL-2.0-only. -- cgit v1.2.3