aboutsummaryrefslogtreecommitdiff
path: root/client/libacron/README.md
diff options
context:
space:
mode:
authorTrumeet <yuuta@yuuta.moe>2022-07-20 18:12:22 -0700
committerTrumeet <yuuta@yuuta.moe>2022-07-20 18:12:22 -0700
commitb4afa06e383325f4a0c751a64ca896d769db07a8 (patch)
tree7647fdd73d4f487de778c27aea99bf890458b647 /client/libacron/README.md
parentda14a17298c67d83e6da4732f47304954acc26fc (diff)
downloadacron-b4afa06e383325f4a0c751a64ca896d769db07a8.tar
acron-b4afa06e383325f4a0c751a64ca896d769db07a8.tar.gz
acron-b4afa06e383325f4a0c751a64ca896d769db07a8.tar.bz2
acron-b4afa06e383325f4a0c751a64ca896d769db07a8.zip
libac: First Commit
Diffstat (limited to 'client/libacron/README.md')
-rw-r--r--client/libacron/README.md199
1 files changed, 199 insertions, 0 deletions
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.