From 7099a86ca74fa637f26af38674f80fb8efd5f6fa Mon Sep 17 00:00:00 2001 From: Trumeet Date: Tue, 26 Jul 2022 17:36:20 -0700 Subject: refactor(libacron/acronc/helloworld): move to separate directories The corresponding CMakeLists.txt files are still rough. --- client/libacron/CMakeLists.txt | 27 +- client/libacron/README.md | 3 - client/libacron/apps/acronc/README.md | 11 - client/libacron/apps/acronc/async_dns.c | 65 ----- client/libacron/apps/acronc/client.c | 114 --------- client/libacron/apps/acronc/client.h | 12 - client/libacron/apps/acronc/common.h | 8 - client/libacron/apps/acronc/config.c | 100 -------- client/libacron/apps/acronc/config.h | 12 - client/libacron/apps/acronc/handler.h | 55 ---- client/libacron/apps/acronc/handler_signal.c | 40 --- client/libacron/apps/acronc/handler_socket.c | 255 ------------------ client/libacron/apps/acronc/handler_stdin.c | 85 ------ client/libacron/apps/acronc/helpers.c | 58 ----- client/libacron/apps/acronc/helpers.h | 24 -- client/libacron/apps/acronc/log.c | 61 ----- client/libacron/apps/acronc/log.h | 52 ---- client/libacron/apps/acronc/main.c | 105 -------- client/libacron/apps/helloworld/main.c | 370 --------------------------- client/libacron/apps/helloworld/net.c | 181 ------------- client/libacron/apps/helloworld/net.h | 45 ---- 21 files changed, 1 insertion(+), 1682 deletions(-) delete mode 100644 client/libacron/apps/acronc/README.md delete mode 100644 client/libacron/apps/acronc/async_dns.c delete mode 100644 client/libacron/apps/acronc/client.c delete mode 100644 client/libacron/apps/acronc/client.h delete mode 100644 client/libacron/apps/acronc/common.h delete mode 100644 client/libacron/apps/acronc/config.c delete mode 100644 client/libacron/apps/acronc/config.h delete mode 100644 client/libacron/apps/acronc/handler.h delete mode 100644 client/libacron/apps/acronc/handler_signal.c delete mode 100644 client/libacron/apps/acronc/handler_socket.c delete mode 100644 client/libacron/apps/acronc/handler_stdin.c delete mode 100644 client/libacron/apps/acronc/helpers.c delete mode 100644 client/libacron/apps/acronc/helpers.h delete mode 100644 client/libacron/apps/acronc/log.c delete mode 100644 client/libacron/apps/acronc/log.h delete mode 100644 client/libacron/apps/acronc/main.c delete mode 100644 client/libacron/apps/helloworld/main.c delete mode 100644 client/libacron/apps/helloworld/net.c delete mode 100644 client/libacron/apps/helloworld/net.h (limited to 'client/libacron') diff --git a/client/libacron/CMakeLists.txt b/client/libacron/CMakeLists.txt index 57ce521..57da4af 100644 --- a/client/libacron/CMakeLists.txt +++ b/client/libacron/CMakeLists.txt @@ -89,32 +89,7 @@ target_link_libraries(ac ${LIBAC_DEPS}) target_include_directories(ac-static PUBLIC ${LIBAC_INCLUDES}) target_link_libraries(ac-static ${LIBAC_DEPS}) -# Apps -if(WIN32) - set(APPS_DEPS ws2_32) -endif() -set(APPS_DEPS ${APPS_DEPS} ac) - -# apps/helloworld -add_executable(helloworld - apps/helloworld/main.c - apps/helloworld/net.c - apps/helloworld/net.h - ) -target_link_libraries(helloworld ${APPS_DEPS}) -target_include_directories(helloworld PUBLIC "${PROJECT_BINARY_DIR}" include/) - -# apps/acronc -add_executable(acronc - apps/acronc/main.c - apps/acronc/common.h - apps/acronc/log.h - apps/acronc/log.c - apps/acronc/handler.h apps/acronc/handler_signal.c apps/acronc/config.c apps/acronc/config.h apps/acronc/client.c apps/acronc/client.h apps/acronc/handler_stdin.c apps/acronc/helpers.c apps/acronc/helpers.h apps/acronc/handler_socket.c apps/acronc/async_dns.c) -target_link_libraries(acronc ${APPS_DEPS} uv) -target_include_directories(acronc PUBLIC "${PROJECT_BINARY_DIR}" include/) - -install(TARGETS ac ac-static helloworld acronc +install(TARGETS ac ac-static EXPORT ${PROJECT_NAME}-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/client/libacron/README.md b/client/libacron/README.md index 418e07b..4514e21 100644 --- a/client/libacron/README.md +++ b/client/libacron/README.md @@ -3,9 +3,6 @@ A client library written in C, based on [json-c](https://github.com/json-c/json-c) and [wic](https://github.com/cjhdev/wic). -This document is for client developers. For users who want a remote console to their Minecraft -server, they should consult [acronc(1)](apps/acronc), a ready-to-use Acron cli. - ## Building Requirements: diff --git a/client/libacron/apps/acronc/README.md b/client/libacron/apps/acronc/README.md deleted file mode 100644 index 87c9db0..0000000 --- a/client/libacron/apps/acronc/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# acronc(1) - -Acron client using libac and libuv, written in C. - -Current status: In development. - -Windows is currently not supported yet. - -## License - -GPL-2.0-only \ No newline at end of file diff --git a/client/libacron/apps/acronc/async_dns.c b/client/libacron/apps/acronc/async_dns.c deleted file mode 100644 index 2e221cf..0000000 --- a/client/libacron/apps/acronc/async_dns.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#include "handler.h" -#include "log.h" - -#include - -static uv_getaddrinfo_t resolv; - -static struct addrinfo *ai = NULL; -static struct addrinfo *ai_current = NULL; -static void (*cb)(int status, - const struct addrinfo *, - void (*on_connect_result)(bool)) = NULL; - -static void on_conn(bool res) { - if (res) { - uv_freeaddrinfo(ai); - ai = NULL; - ai_current = NULL; - cb = NULL; - return; - } - ai_current = ai_current->ai_next; - if (!ai_current) { - /* No more result available. */ - cb(1, NULL, NULL); - uv_freeaddrinfo(ai); - ai = NULL; - ai_current = NULL; - cb = NULL; - return; - } - cb(0, ai_current, &on_conn); -} - -static void on_resolv(uv_getaddrinfo_t *req, int status, struct addrinfo *res) { - LOGDV("on_resolv(req = %p): status = %d, res = %p", - req, - status, - res); - if (status) { - LOGEV("Cannot resolve host: %s", uv_strerror(status)); - cb(status, NULL, NULL); - return; - } - ai = res; - ai_current = res; - cb(0, ai_current, &on_conn); -} - -int a_dns(const char *host, - uint16_t port, - void (*c)(int status, - const struct addrinfo *, - void (*on_connect_result)(bool))) { - int r; - char service[6]; - snprintf(service, 6, "%u", port); - cb = c; - if ((r = uv_getaddrinfo(loop, &resolv, on_resolv, host, service, NULL))) return r; - return 0; -} diff --git a/client/libacron/apps/acronc/client.c b/client/libacron/apps/acronc/client.c deleted file mode 100644 index 5553d4c..0000000 --- a/client/libacron/apps/acronc/client.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#include "client.h" -#include "helpers.h" - -#include -#include - -static void handle_event(const ac_event_t *event) { - switch (event->type) { - case AC_EVENT_LAGGING: { - ac_event_lagging_t *o = (ac_event_lagging_t *) event; - printf("Server lagging: running %ld milliseconds (%ld ticks) behind.\n", - o->ms, - o->ticks); - break; - } - case AC_EVENT_ENTITY_DEATH: { - ac_event_entity_death_t *o = (ac_event_entity_death_t *) event; - printf("Entity '%s' died at %s(%.2f, %.2f, %.2f): %s.\n", - o->entity.name, - world_name(o->entity.world), - o->entity.pos.x, - o->entity.pos.y, - o->entity.pos.z, - o->message); - break; - } - case AC_EVENT_PLAYER_MESSAGE: { - ac_event_player_message_t *o = (ac_event_player_message_t *) event; - printf("Player '%s' said at %s(%.2f, %.2f, %.2f): %s.\n", - o->player.name, - world_name(o->player.world), - o->player.pos.x, - o->player.pos.y, - o->player.pos.z, - o->text); - break; - } - case AC_EVENT_PLAYER_DISCONNECT: { - ac_event_player_disconnect_t *o = (ac_event_player_disconnect_t *) event; - printf("Player '%s' disconnected at %s(%.2f, %.2f, %.2f): %s.\n", - o->player.name, - world_name(o->player.world), - o->player.pos.x, - o->player.pos.y, - o->player.pos.z, - o->reason); - break; - } - case AC_EVENT_PLAYER_JOIN: { - ac_event_player_join_t *o = (ac_event_player_join_t *) event; - printf("Player '%s' joined at %s(%.2f, %.2f, %.2f).\n", - o->player.name, - world_name(o->player.world), - o->player.pos.x, - o->player.pos.y, - o->player.pos.z); - break; - } - default: { - printf("Received an unrecognized event of type '%u'.\n", - event->type); - } - } -} - -static void handle_response(const ac_response_t *response) { - switch (response->type) { - case AC_RESPONSE_OK: { - ac_response_ok_t *o = (ac_response_ok_t *) response; - printf("Request %d OK.\n", - o->id); - break; - } - case AC_RESPONSE_ERROR: { - ac_response_error_t *o = (ac_response_error_t *) response; - printf("Request %d failed: %s (%d).\n", - o->id, - o->message, - o->code); - break; - } - case AC_RESPONSE_CMD_OUT: { - ac_response_cmd_out_t *o = (ac_response_cmd_out_t *) response; - printf("Request %d output by %s: %s.\n", - o->id, - o->sender, - o->out); - break; - } - case AC_RESPONSE_CMD_RESULT: { - ac_response_cmd_result_t *o = (ac_response_cmd_result_t *) response; - printf("Request %d is done: %s (%d).\n", - o->id, - o->success ? "Success" : "Failed", - o->result); - break; - } - default: { - printf("Received an unrecognized response of type '%u'.\n", - response->type); - } - } -} - -int handle_object(ac_obj_t *obj) { - if (AC_IS_RESPONSE(obj->type)) handle_response((ac_response_t *) obj); - else handle_event((ac_event_t *) obj); - ac_object_free(obj); - return 0; -} \ No newline at end of file diff --git a/client/libacron/apps/acronc/client.h b/client/libacron/apps/acronc/client.h deleted file mode 100644 index 438d7fd..0000000 --- a/client/libacron/apps/acronc/client.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#ifndef ACRONC_CLIENT_H -#define ACRONC_CLIENT_H - -#include - -int handle_object(ac_obj_t *obj); - -#endif /* ACRONC_CLIENT_H */ diff --git a/client/libacron/apps/acronc/common.h b/client/libacron/apps/acronc/common.h deleted file mode 100644 index 0ca3b92..0000000 --- a/client/libacron/apps/acronc/common.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Created by yuuta on 7/23/22. - */ - -#ifndef ACRONC_COMMON_H -#define ACRONC_COMMON_H - -#endif /* ACRONC_COMMON_H */ diff --git a/client/libacron/apps/acronc/config.c b/client/libacron/apps/acronc/config.c deleted file mode 100644 index 046d931..0000000 --- a/client/libacron/apps/acronc/config.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -int config_parse(const int argc, const char **argv, ac_connection_parameters_t *params) { - if (argc <= 1) { - fprintf(stderr, "Usage: %s [-t token] [-p port] @\n" - "Please refer to acronc(1) for more details.\n", - argv[0] ? "acronc" : argv[0]); - return 64; - } - bool svr_set = false; - for (int i = 1; i < argc; i++) { - const char *arg = argv[i]; - if (arg[0] != '-') { - if (svr_set) { - fprintf(stderr, "Unexpected value: %s\n", arg); - return 64; - } - const char *id = strtok((char *) arg, "@"); - if (!id) { - fprintf(stderr, "Malformed argument: should be ID@server.\n"); - return 64; - } - const char *server = strtok(NULL, ""); - if (!server) { - fprintf(stderr, "Malformed argument: should be ID@server.\n"); - return 64; - } - params->host = (char *) server; - params->id = (char *) id; - svr_set = true; - continue; - } - char a = arg[1]; - char **value_ptr; - char *port_str = NULL; - switch (a) { - case 't': { - value_ptr = ¶ms->token; - goto read_value; - } - case 'p': { - value_ptr = &port_str; - goto read_value; - } - default: { - fprintf(stderr, "Unexpected switch -%c.\n", a); - return 64; - } - } - read_value: - { - if (i == (argc - 1)) { - fprintf(stderr, "-%c requires an argument.\n", a); - return 64; - } - *value_ptr = (char *) argv[++i]; - } - if (port_str) { - errno = 0; - char *endptr; - unsigned long val = strtol(port_str, &endptr, 0); - if (errno) { - const int e = errno; - fprintf(stderr, "Cannot parse port: %s", strerror(e)); - return e; - } - if (endptr == port_str) { - fprintf(stderr, "Illegal port.\n"); - return 64; - } - if (val > UINT16_MAX) { - fprintf(stderr, "Illegal port.\n"); - return 64; - } - params->port = (uint16_t) val; - port_str = NULL; - } - } - if (!params->host || !params->id) { - fprintf(stderr, "Usage: acronc ID@server[:port]\n"); - return 64; - } - char tok[1024]; - if (!params->token) { - printf("Token: "); - scanf("%1023[^\n]", tok); - params->token = tok; - } - return 0; -} \ No newline at end of file diff --git a/client/libacron/apps/acronc/config.h b/client/libacron/apps/acronc/config.h deleted file mode 100644 index ee51f34..0000000 --- a/client/libacron/apps/acronc/config.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#ifndef ACRONC_CONFIG_H -#define ACRONC_CONFIG_H - -#include - -int config_parse(int argc, const char **argv, ac_connection_parameters_t *params); - -#endif /* ACRONC_CONFIG_H */ diff --git a/client/libacron/apps/acronc/handler.h b/client/libacron/apps/acronc/handler.h deleted file mode 100644 index 1a2ccfe..0000000 --- a/client/libacron/apps/acronc/handler.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#ifndef ACRONC_HANDLER_H -#define ACRONC_HANDLER_H - -#include -#include - -enum exit_reason { - /* Exit due to a signal. Socket is working. */ - EXIT_SIGNAL, - /* Exit due to an EOF from stdin. Socket is working. */ - EXIT_STDIN_EOF, - /* Exit due to an EOF from socket. Socket is closed. */ - EXIT_SOCKET_EOF, - /* Exit due to a socket failure. Socket is closed. */ - EXIT_FAILURE_SOCKET, - /* Exit due to a failure. Socket is working. */ - EXIT_FAILURE -}; - -struct uv_obj { - void *obj; - bool running; -}; - -extern uv_loop_t *loop; - -extern void (*on_exit)(enum exit_reason reason); - -int h_signal(void); - -int h_stdin(int (*on_input)(ac_request_t *req), - void (*on_close)(void)); - -int h_socket(ac_connection_parameters_t *p, - const struct addrinfo *ai, - void (*on_connect_result)(bool), - int (*on_ready)(void), - int (*on_received)(ac_obj_t *obj), - void (*on_closed)(void)); - -int sock_request(ac_request_t *req); - -int sock_ext(bool trigger_callback); - -int a_dns(const char *host, - uint16_t port, - void (*on_resolv)(int status, - const struct addrinfo *, - void (*on_connect_result)(bool))); - -#endif /* ACRONC_HANDLER_H */ diff --git a/client/libacron/apps/acronc/handler_signal.c b/client/libacron/apps/acronc/handler_signal.c deleted file mode 100644 index 1d0ba7e..0000000 --- a/client/libacron/apps/acronc/handler_signal.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#include "handler.h" -#include "log.h" - -static uv_signal_t sigint; -static struct uv_obj obj_sigint = { - .obj = &sigint, - .running = false -}; -static uv_signal_t sigterm; -static struct uv_obj obj_sigterm = { - .obj = &sigterm, - .running = false -}; - -static void on_signal(uv_signal_t *handle, int signum) { - LOGDV("on_signal(handle = %p): %d", - handle, - signum); - uv_signal_stop(&sigint); - obj_sigint.running = false; - uv_signal_stop(&sigterm); - obj_sigterm.running = false; - on_exit(EXIT_SIGNAL); -} - -int h_signal(void) { - int r; - if ((r = uv_signal_init(loop, &sigint))) return r; - if ((r = uv_signal_start(&sigint, on_signal, SIGINT))) return r; - - obj_sigint.running = true; - if ((r = uv_signal_init(loop, &sigterm))) return r; - if ((r = uv_signal_start(&sigterm, on_signal, SIGTERM))) return r; - obj_sigterm.running = true; - return 0; -} diff --git a/client/libacron/apps/acronc/handler_socket.c b/client/libacron/apps/acronc/handler_socket.c deleted file mode 100644 index ff8eefb..0000000 --- a/client/libacron/apps/acronc/handler_socket.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#include "handler.h" -#include "log.h" -#include "helpers.h" - -#include -#include -#include - -static void (*cb_conn)(bool); - -static int (*cb_ready)(void); - -static int (*cb_recv)(ac_obj_t *obj); - -static void (*cb_close)(void); - -static ac_connection_parameters_t *params; - -static uv_tcp_t sock; -static uv_write_t write; - -static uv_connect_t conn; - -static bool ready = false; -static void *ac_conn = NULL; - -#define RUNNING !uv_is_closing((uv_handle_t *) &sock) - -static void on_close(uv_handle_t *handle) { - LOGDV("on_close(handle = %p)", - handle); - if (handle->data) - cb_close(); -} - -static void ex2(bool force, bool cb) { - LOGDV("Exiting socket handlers: Force WebSocket close: %s; Socket still running: %s.", - force ? "true" : "false", - RUNNING ? "true" : "false"); - if (ac_conn) { - ac_disconnect(ac_conn, - RUNNING ? force : true /* If sock is not running, always force */); - ac_conn = NULL; - } - if (RUNNING) { - sock.data = cb ? &ex2 /* Any non-NULL value */ : NULL; - uv_close((uv_handle_t *) &sock, on_close); - } else { - if (cb) { - cb_close(); - } - } -} - -static void ex(bool force) { - ex2(force, true); -} - -int sock_ext(bool trigger_callback) { - ex2(false, trigger_callback); - return 0; -} - -static void on_alloc(uv_handle_t *handle, size_t size, uv_buf_t *buf) { - LOGDV("on_alloc(handle = %p): size = %lu", - handle, - size); - void *b = malloc(size); - if (!b) { - LOGEV("Cannot allocate memory of %u bytes: %s.", - size, - strerror(errno)); - /* Socket is still working now. */ - ex(false); - *buf = uv_buf_init(NULL, 0); /* Just in case? */ - return; - } - *buf = uv_buf_init(b, size); -} - -static void on_read(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) { - LOGDV("on_read(stream = %p): nread = %ld, buf = %p, buf->base = %p, buf->len = %lu", - tcp, - nread, - buf, buf->base, buf->len); - if (!nread) { - /* EAGAIN */ - if (buf->base) free(buf->base); - return; - } - if (nread == UV_EOF) { - LOGW("Received EOF from server."); - free(buf->base); - /* The socket * should * be closed already? */ - ex(true); - return; - } - if (nread < 0) { - LOGEV("Encountered a failure while reading from the socket: ", uv_strerror(nread)); - if (buf->base) free(buf->base); - /* Docs: The callee is responsible for stopping/closing the stream when an error happens */ - ex(true); /* Force close libac connection here. */ - return; - } - int r; - ac_obj_t *obj = NULL; - if ((r = ac_receive(ac_conn, buf->base, nread, &obj))) { - LOGEV("Cannot parse the response (%d).", r); - /* libac error. Socket is working. */ - ex(false); - return; - } - - if (!ready) { - enum ac_connection_state state; - if ((r = ac_get_state(ac_conn, &state))) { - LOGEV("Cannot get state (%d).", r); - /* libac error. Socket is working. */ - ex(false); - return; - } - if (state == AC_STATE_READY) { - ready = true; - if ((cb_ready())) { - /* acronc error. Socket is working. */ - ex(false); - return; - } - } - } - if (obj) { - LOGDV("Got object: %p", obj); - /* uv_async_send is unreliable, and missed messages will cause memory leak. */ - if (cb_recv(obj)) { - /* acronc error. Socket is working. */ - ex(false); - } - } - - free(buf->base); -} - -static void on_write(uv_write_t *req, int status) { - LOGDV("on_write(req = %p): %d", - req, - status); - if (status) { - LOGEV("Cannot write to socket: %s", uv_strerror(status)); - /* Socket may be closed? Anyway writing again will definitely be problematic, but closing may not. */ - ex(true); - } -} - -static int on_send(const void *s, - const void *buf, - const size_t len) { - LOGDV("on_send(s = %p): len = %u", - s, - len); - const uv_stream_t *stream = s; - uv_buf_t buffer[] = { - {.base = (char *) buf, .len = len} - }; - int r; - if ((r = uv_write(&write, (uv_stream_t *) stream, buffer, 1, on_write))) { - LOGEV("Cannot write to socket: %s", uv_strerror(r)); - /* Socket may be closed? Anyway writing again will definitely be problematic, but closing may not. */ - ex(true); - } - return 0; -} - -static void on_retry_closed(uv_handle_t *handle) { - cb_conn(false); -} - -static void on_connect(uv_connect_t *req, int status) { - LOGDV("on_connect(req = %p): status = %d", - req, - status); - if (status) { - LOGEV("Cannot connect to the server: %s", uv_strerror(status)); - /* Close it for the next retry. */ - if (RUNNING) { - LOGD("Closing socket before retry."); - uv_close((uv_handle_t *) &sock, on_retry_closed); - } else { - cb_conn(false); - } - return; - } - LOGI("Connected."); - uv_stream_t *stream = req->handle; - int r; - params->sock = stream; - if ((r = ac_connect(*params, &ac_conn))) { - LOGEV("Cannot initialize connection: %d.", r); - cb_conn(false); - return; - } - if ((r = uv_read_start(stream, on_alloc, on_read))) { - LOGEV("Cannot read socket: %s", uv_strerror(r)); - cb_conn(false); - return; - } - cb_conn(true); -} - -int h_socket(ac_connection_parameters_t *p, - const struct addrinfo *ai, - void (*on_connect_result)(bool), - int (*on_ready)(void), - int (*on_received)(ac_obj_t *obj), - void (*on_closed)(void)) { - cb_conn = on_connect_result; - cb_ready = on_ready; - cb_recv = on_received; - cb_close = on_closed; - params = p; - params->on_send = on_send; - - struct sockaddr *sa = ai->ai_addr; - LOGIV("Connecting to %s...", ntop(sa)); - int r; - if ((r = uv_tcp_init(loop, &sock))) { - LOGEV("Cannot initialize the socket: %s", uv_strerror(r)); - return r; - } - if ((r = uv_tcp_connect(&conn, &sock, sa, on_connect))) { - LOGEV("Cannot initialize the connection: %s", uv_strerror(r)); - return r; - } - return 0; -} - -int sock_request(ac_request_t *req) { - if (!ac_conn) { - /* Just in case. */ - LOGE("sock_request() called on a closed socket."); - /* Ignore it. */ - return 0; - } - int r = ac_request(ac_conn, req); - if (r) { - LOGEV("Cannot send request: %d.", r); - /* libac error. Socket is working. */ - ex(false); - } - return r; -} - diff --git a/client/libacron/apps/acronc/handler_stdin.c b/client/libacron/apps/acronc/handler_stdin.c deleted file mode 100644 index 3ac307d..0000000 --- a/client/libacron/apps/acronc/handler_stdin.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#include "handler.h" -#include "log.h" - -#include -#include - -static unsigned int id = 0; - -static uv_tty_t tty; - -static int (*cb_recv)(ac_request_t *req); - -static void (*cb_close)(void); - -static void on_close(uv_handle_t *handle) { - cb_close(); -} - -static void on_alloc(uv_handle_t *handle, size_t size, uv_buf_t *buf) { - LOGDV("on_alloc(handle = %p): size = %lu", - handle, - size); - void *b = malloc(size); - if (!b) { - LOGEV("Cannot allocate memory of %u bytes: %s.", - size, - strerror(errno)); - /* Stream is still working now. */ - uv_close(handle, on_close); - *buf = uv_buf_init(NULL, 0); /* Just in case? */ - return; - } - *buf = uv_buf_init(b, size); -} - -static void on_stdin(uv_stream_t *t, ssize_t nread, const uv_buf_t *buf) { - LOGDV("on_stdin(stream = %p): nread = %ld, buf = %p, buf->base = %p, buf->len = %lu", - t, - nread, - buf, buf->base, buf->len); - if (!nread) { - if (buf->base) free(buf->base); - return; - } - if (nread == UV_EOF) { - LOGI("Exit."); - free(buf->base); - - cb_close(); - return; - } - if (nread < 0) { - LOGEV("Encountered a failure while reading stdin: ", uv_strerror(nread)); - if (buf->base) free(buf->base); - uv_close((uv_handle_t *) t, on_close); - return; - } - buf->base[nread - 1] = '\0'; /* Remove junk and tailing \n */ - if ((++ id) > INT_MAX) { - id = 0; - } - ac_request_cmd_t req = { - .type = AC_REQUEST_CMD, - .id = (int) id, - .cmd = buf->base - }; - if (cb_recv((ac_request_t *) &req)) { - uv_close((uv_handle_t *) t, on_close); - } - free(buf->base); -} - -int h_stdin(int (*on_input)(ac_request_t *req), - void (*on_close)(void)) { - cb_recv = on_input; - cb_close = on_close; - int r; - if ((r = uv_tty_init(loop, &tty, 0, 0))) return r; - if ((r = uv_read_start((uv_stream_t *) &tty, on_alloc, on_stdin))) return r; - return 0; -} \ No newline at end of file diff --git a/client/libacron/apps/acronc/helpers.c b/client/libacron/apps/acronc/helpers.c deleted file mode 100644 index 9e141d4..0000000 --- a/client/libacron/apps/acronc/helpers.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#include "helpers.h" - -#include -#include -#include - -#ifdef WIN32 -#include -#include -#include - -#define errno_sock WSAGetLastError() - -#else - -#include -#include - -#define errno_sock errno - -#endif - -const char *ntop(const struct sockaddr *sa) { - static char buf[INET6_ADDRSTRLEN]; - const char *retval; - switch (sa->sa_family) { - case AF_INET: { - retval = inet_ntop(AF_INET, &((struct sockaddr_in *) sa)->sin_addr, buf, sizeof(buf)); - break; - } - case AF_INET6: { - retval = inet_ntop(AF_INET6, &((struct sockaddr_in6 *) sa)->sin6_addr, buf, sizeof(buf)); - break; - } - default: { - return "Unknown address family"; - } - } - if (retval) return retval; - return strerror(errno_sock); -} - -const char *world_name(const enum ac_world world) { - switch (world) { - case overworld: - return "overworld"; - case nether: - return "nether"; - case end: - return "end"; - default: - return "unknown world"; - } -} diff --git a/client/libacron/apps/acronc/helpers.h b/client/libacron/apps/acronc/helpers.h deleted file mode 100644 index e983439..0000000 --- a/client/libacron/apps/acronc/helpers.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Created by yuuta on 7/24/22. - */ - -#ifndef ACRONC_HELPERS_H -#define ACRONC_HELPERS_H - -#include - -#ifdef WIN32 -#include -#include - -#else - -#include - -#endif - -const char *ntop(const struct sockaddr *sa); - -const char *world_name(enum ac_world world); - -#endif /* ACRONC_HELPERS_H */ diff --git a/client/libacron/apps/acronc/log.c b/client/libacron/apps/acronc/log.c deleted file mode 100644 index 08f48b6..0000000 --- a/client/libacron/apps/acronc/log.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Created by yuuta on 1/1/22. - */ - -#define _GNU_SOURCE - -#include "log.h" -#include "config.h" - -#include -#include -#include - -#ifdef __linux__ -#include -#include -#include -#endif - -void g_log(enum log_level level, - const char *file, - int line, - const char *format, - ...) { - FILE *stream = stderr; - switch (level) { - case log_fetal: - fprintf(stream, "F"); - break; - case log_error: - fprintf(stream, "E"); - break; - case log_warn: - fprintf(stream, "W"); - break; - case log_info: - fprintf(stream, "I"); - break; - case log_debug: -#ifdef DEBUG - fprintf(stream, "D"); - break; -#else - return; -#endif - default: - fprintf(stderr, "Unknown log level: %d.\n", level); - assert(0); - } - int tid = -1; -#ifdef __linux__ - tid = (int) syscall(__NR_gettid); -#endif - fprintf(stream, "[%d %s:%d]: ", - tid, file, line); - va_list list; - va_start(list, format); - vfprintf(stream, format, list); - va_end(list); - fprintf(stream, "\n"); -} diff --git a/client/libacron/apps/acronc/log.h b/client/libacron/apps/acronc/log.h deleted file mode 100644 index 7bc9532..0000000 --- a/client/libacron/apps/acronc/log.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Created by yuuta on 1/1/22. - */ - -#ifndef LOG_H -#define LOG_H - -enum log_level { - log_fetal = 1, - log_error = 2, - log_warn = 3, - log_info = 4, - log_debug = 5 -}; - -void g_log(enum log_level level, - const char *file, - int line, - const char *format, - ...); - -#define LOGF(X) g_log(log_fetal, __FUNCTION__, __LINE__, X) - -#define LOGFV(X, ...) g_log(log_fetal, __FUNCTION__, __LINE__, X, __VA_ARGS__) - -#define LOGE(X) g_log(log_error, __FUNCTION__, __LINE__, X) - -#define LOGEV(X, ...) g_log(log_error, __FUNCTION__, __LINE__, X, __VA_ARGS__) - -#define LOGW(X) g_log(log_warn, __FUNCTION__, __LINE__, X) - -#define LOGWV(X, ...) g_log(log_warn, __FUNCTION__, __LINE__, X, __VA_ARGS__) - -#define LOGI(X) g_log(log_info, __FUNCTION__, __LINE__, X) - -#define LOGIV(X, ...) g_log(log_info, __FUNCTION__, __LINE__, X, __VA_ARGS__) - -#ifdef DEBUG - -#define LOGD(X) g_log(log_debug, __FUNCTION__, __LINE__, X) - -#define LOGDV(X, ...) g_log(log_debug, __FUNCTION__, __LINE__, X, __VA_ARGS__) - -#else - -#define LOGD(X) - -#define LOGDV(X, ...) - -#endif - -#endif /* LOG_H */ diff --git a/client/libacron/apps/acronc/main.c b/client/libacron/apps/acronc/main.c deleted file mode 100644 index 6e18ed2..0000000 --- a/client/libacron/apps/acronc/main.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Created by yuuta on 7/23/22. - */ - -#include "log.h" -#include "handler.h" -#include "config.h" -#include "helpers.h" -#include "client.h" - -#include -#include -#include -#include -#include -#include - -static uv_loop_t lop; -uv_loop_t *loop = &lop; - -static void on_close(uv_handle_t *handle); - -static ac_connection_parameters_t params = { - .sock = NULL, - .version = 0, - .port = 25575, - .host = NULL, - .id = NULL, - .token = NULL, - .on_send = NULL, -}; - -static void cleanup(void) { - LOGD("cleanup()"); - /* sock must be closed before cleanup(). */ - uv_loop_close(loop); - ac_free(); - uv_tty_reset_mode(); -} - -static void on_stdin_closed(void) { - sock_ext(true); -} - -static void on_sock_closed(void) { - uv_stop(loop); -} - -static int on_input(ac_request_t *req) { - /* The socket will close itself upon errors. So do the input stream. */ - return sock_request(req); -} - -static int on_sock_ready(void) { - return h_stdin(on_input, on_stdin_closed); -} - -static void on_resolv(int status, const struct addrinfo *ai, void (*on_connected)(bool)) { - if (status) { - uv_stop(loop); - return; - } - - if (h_socket(¶ms, - ai, - on_connected, - on_sock_ready, - handle_object, - on_sock_closed)) { - /* Mark as true to clean up resources and prevent next retry. */ - on_connected(true); - uv_stop(loop); - } -} - -int main(int argc, const char **argv) { - int r; - - if ((r = config_parse(argc, argv, ¶ms))) return r; - atexit(cleanup); - libac_config_t config = { -#ifdef DEBUG - .out = NULL, -#else - .out = NULL, -#endif - .tok = NULL - }; - if ((r = ac_init(&config))) errx(r, "Cannot initialize Acron library."); - - if ((r = uv_loop_init(loop))) goto uviniterr; - if ((r = h_signal())) goto uviniterr; - if ((r = a_dns(params.host, params.port, on_resolv))) goto uviniterr; - - if ((r = uv_run(loop, UV_RUN_DEFAULT))) { - if (r == 1) { - /* Seems to return 1 if uv_stop is called. */ - return 0; - } - errx(-r, "Cannot run: %s", uv_strerror(r)); - } - return 0; - uviniterr: - errx(-r, "Cannot initialize: %s", uv_strerror(r)); -} \ No newline at end of file diff --git a/client/libacron/apps/helloworld/main.c b/client/libacron/apps/helloworld/main.c deleted file mode 100644 index c112fcb..0000000 --- a/client/libacron/apps/helloworld/main.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Created by yuuta on 7/20/22. - */ - -#include "libac.h" -#include "net.h" - -#include - -#ifndef WIN32 - -#include -#include -#include - -#endif - -#ifdef __STDC_NO_THREADS__ -# ifdef WIN32 -#define THREAD_WIN32 -#include -static HANDLE mtx_conn; - -int lock(void) { \ -DWORD _dwlck = WaitForSingleObject(mtx_conn, 0); \ -if (_dwlck == WAIT_FAILED) { _dwlck = GetLastError(); } \ -if (_dwlck) { fprintf(stderr, "Cannot lock the mutex: %d.\n", _dwlck); return _dwlck; } \ -return 0; \ -} - -int unlock(void) { \ -if (!ReleaseMutex(mtx_conn)) { \ -int r = GetLastError(); \ -fprintf(stderr, "Cannot release the mutex: %d.\n", r); \ -return r; \ -} \ -return 0; \ -} - -# else -#error "Either C11 threading or Win32 API is required for concurrency." -# endif -#else - -#define THREAD_C11 - -#include - -static mtx_t mtx_conn; - -int lock(void) { - \ -if (mtx_lock(&mtx_conn) != thrd_success) { - \ -fprintf(stderr, "Cannot lock the mutex.\n"); \ -return 1; \ - - } \ -return 0; \ - -} - -int unlock(void) { - \ -if (mtx_unlock(&mtx_conn) != thrd_success) { - \ -fprintf(stderr, "Cannot release the mutex.\n"); \ -return 1; \ - - } \ -return 0; \ - -} - -#endif - -static const char *world_name(const enum ac_world world) { - switch (world) { - case overworld: - return "overworld"; - case nether: - return "nether"; - case end: - return "end"; - default: - return "unknown world"; - } -} - -static void handle_event(const ac_event_t *event) { - switch (event->type) { - case AC_EVENT_LAGGING: { - ac_event_lagging_t *o = (ac_event_lagging_t *) event; - printf("Server lagging: running %ld milliseconds (%ld ticks) behind.\n", - o->ms, - o->ticks); - break; - } - case AC_EVENT_ENTITY_DEATH: { - ac_event_entity_death_t *o = (ac_event_entity_death_t *) event; - printf("Entity '%s' died at %s(%.2f, %.2f, %.2f): %s.\n", - o->entity.name, - world_name(o->entity.world), - o->entity.pos.x, - o->entity.pos.y, - o->entity.pos.z, - o->message); - break; - } - case AC_EVENT_PLAYER_MESSAGE: { - ac_event_player_message_t *o = (ac_event_player_message_t *) event; - printf("Player '%s' said at %s(%.2f, %.2f, %.2f): %s.\n", - o->player.name, - world_name(o->player.world), - o->player.pos.x, - o->player.pos.y, - o->player.pos.z, - o->text); - break; - } - case AC_EVENT_PLAYER_DISCONNECT: { - ac_event_player_disconnect_t *o = (ac_event_player_disconnect_t *) event; - printf("Player '%s' disconnected at %s(%.2f, %.2f, %.2f): %s.\n", - o->player.name, - world_name(o->player.world), - o->player.pos.x, - o->player.pos.y, - o->player.pos.z, - o->reason); - break; - } - case AC_EVENT_PLAYER_JOIN: { - ac_event_player_join_t *o = (ac_event_player_join_t *) event; - printf("Player '%s' joined at %s(%.2f, %.2f, %.2f).\n", - o->player.name, - world_name(o->player.world), - o->player.pos.x, - o->player.pos.y, - o->player.pos.z); - break; - } - default: { - printf("Received an unrecognized event of type '%u'.\n", - event->type); - } - } -} - -static void handle_response(const ac_response_t *response) { - switch (response->type) { - case AC_RESPONSE_OK: { - ac_response_ok_t *o = (ac_response_ok_t *) response; - printf("Request %d OK.\n", - o->id); - break; - } - case AC_RESPONSE_ERROR: { - ac_response_error_t *o = (ac_response_error_t *) response; - printf("Request %d failed: %s (%d).\n", - o->id, - o->message, - o->code); - break; - } - case AC_RESPONSE_CMD_OUT: { - ac_response_cmd_out_t *o = (ac_response_cmd_out_t *) response; - printf("Request %d output by %s: %s.\n", - o->id, - o->sender, - o->out); - break; - } - case AC_RESPONSE_CMD_RESULT: { - ac_response_cmd_result_t *o = (ac_response_cmd_result_t *) response; - printf("Request %d is done: %s (%d).\n", - o->id, - o->success ? "Success" : "Failed", - o->result); - break; - } - default: { - printf("Received an unrecognized response of type '%u'.\n", - response->type); - } - } -} - -#ifndef WIN32 - -static void intr(int signum) {} - -#endif - -static int on_send(const void *sock, - const void *buffer, - const size_t len) { - int r; - printf("Writing %lu bytes.\n", len); - if ((r = net_send(sock, buffer, len))) { - fprintf(stderr, "Cannot write %lu bytes to server: %s (%d).\n", - len, - net_strerror(r), - r); - } - return r; -} - -static int say(void *connection) { - int r; - ac_config_t conf = { - .name = "helloworld" - }; - ac_request_cmd_t req = { - .type = AC_REQUEST_CMD, - .id = 100, - .config = &conf, - .cmd = "say Hi" - }; - if ((r = ac_request(connection, (ac_request_t *) &req))) { - return r; - } - return 0; -} - -int main(int argc, char **argv) { - int r; - if ((r = net_init())) { - return r; - } -#if defined(THREAD_WIN32) - if (!(mtx_conn = CreateMutex(NULL, TRUE, NULL))) { - r = GetLastError(); - fprintf(stderr, "Cannot create mutex: %d.\n", r); - return r; - } -#elif defined(THREAD_C11) - if (mtx_init(&mtx_conn, mtx_plain) != thrd_success) { - fprintf(stderr, "Cannot create mutex.\n"); - return 1; - } -#endif - -#ifdef WIN32 - fprintf(stderr, "Warning: ^C handler on Windows is not yet available.\n"); -#else - struct sigaction sa; - sa.sa_handler = intr; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - if (sigaction(SIGINT, &sa, NULL) || - sigaction(SIGTERM, &sa, NULL)) { - const int e = errno; - fprintf(stderr, "Cannot set SIGINT or SIGTERM handlers: %s (%d).\n", - strerror(e), - e); - return e; - } -#endif - libac_config_t config = { -#ifdef DEBUG - .out = stderr, -#else - .out = NULL, -#endif - .tok = NULL - }; - if ((r = ac_init(&config))) return r; - void *connection; - SOCKET sock; - ac_connection_parameters_t parameters = { - .host = "localhost", - .port = 25575, - .id = "1", - .token = "123", - .version = 0, - .sock = NULL, - .on_send = on_send - }; - if ((r = net_connect(parameters.host, parameters.port, &sock))) { - fprintf(stderr, "Cannot connect to server: %s (%d).\n", - net_strerror(r), - r); - ac_free(); - net_free(); - return r; - } - parameters.sock = &sock; - if ((r = ac_connect(parameters, &connection))) { - net_close(&sock); - ac_free(); - net_free(); - return r; - } - ac_obj_t *obj; - int nr; - uint8_t buffer[1000U]; - size_t bytes; - enum ac_connection_state state; - printf("Waiting until the connection is established.\n"); - bool ready = false; - while (1) { - if ((nr = net_read(&sock, buffer, sizeof(buffer), &bytes, 10))) { - if (nr == NET_TIMEOUT) { - printf("Receive timeout.\n"); - continue; - } else { - goto end; - } - } - if ((r = lock())) { goto end; } - if ((r = ac_receive(connection, buffer, bytes, &obj))) { - if ((r = unlock())) { goto end; } - goto end; - } - if (!ready) { - /* Wait until ready. */ - if ((r = ac_get_state(connection, &state))) { - if ((r = unlock())) { goto end; } - goto end; - } - switch (state) { - case AC_STATE_INIT: - continue; - case AC_STATE_READY: - printf("Connection is established.\n"); - ready = true; - say(connection); - if ((r = unlock())) { goto end; } - continue; - default: - fprintf(stderr, "Unexpected state.\n"); - if ((r = unlock())) { goto end; } - goto end; - } - } - if ((r = unlock())) { goto end; } - - if (!obj) { - continue; - } - if (AC_IS_EVENT(obj->type)) { - handle_event((ac_event_t *) obj); - } else if (AC_IS_RESPONSE(obj->type)) { - handle_response((ac_response_t *) obj); - } - ac_object_free(obj); - } - end: - if (nr) { - if (nr == NET_CLOSED) { - fprintf(stderr, "Connection is closed while reading from the server.\n"); - } else { - fprintf(stderr, "Cannot receive from server: %s (%d).\n", - net_strerror(nr), - nr); - } - } - if ((r = lock())) { goto end; } - ac_disconnect(connection, false); - if ((r = unlock())) { goto end; } - net_close(&sock); - ac_free(); - net_free(); -#if defined(THREAD_WIN32) - CloseHandle(mtx_conn); -#elif defined(THREAD_C11) - mtx_destroy(&mtx_conn); -#endif - return r; -} \ No newline at end of file diff --git a/client/libacron/apps/helloworld/net.c b/client/libacron/apps/helloworld/net.c deleted file mode 100644 index 83192e0..0000000 --- a/client/libacron/apps/helloworld/net.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Created by yuuta on 7/22/22. - * - * A simple cross-platform (Unix and Windows) implementation of a socket client. - */ - -#include "net.h" - -#include -#include -#include -#include - -#ifdef WIN32 -#include /* For DWORD */ -#include -#include - -#define errno_sock WSAGetLastError() - -#else - -#include -#include -#include -#include - -#define closesocket(socket) close(socket) -#define errno_sock errno - -#endif - -int net_connect(const char *host, - const uint16_t port, - SOCKET *sock) { - int r; - struct addrinfo *res; - char service[6]; - - snprintf(service, 6, "%u", port); - if ((r = getaddrinfo(host, service, NULL, &res))) { - return r; - } - - SOCKET fd; - if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) <= 0) { - const int e = errno_sock; - freeaddrinfo(res); - return e; - } - if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) { - const int e = errno_sock; - closesocket(fd); - freeaddrinfo(res); - return e; - } - freeaddrinfo(res); - *sock = fd; - return 0; -} - -int net_read(const SOCKET *sock, - void *buffer, - const size_t length, - size_t *read, - const unsigned int timeout) { - -#ifdef WIN32 - DWORD to = timeout * 1000; - if (setsockopt(*sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&to, sizeof to)) { -#else - struct timeval tv; - tv.tv_sec = timeout; - tv.tv_usec = 0; - if (setsockopt(*sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &tv, sizeof tv)) { -#endif - return errno_sock; - } - - int bytes; - if ((bytes = (int) recv(*sock, buffer, length, 0)) <= 0) { - if (bytes < 0) { - const int e = errno_sock; -#ifdef WIN32 - if (e == WSAETIMEDOUT) { -#else - if (e == EAGAIN) { -#endif - return NET_TIMEOUT; - } - return e; - } - return NET_CLOSED; - } - *read = bytes; - return 0; -} - -int net_send(const SOCKET *sock, - const void *buffer, - size_t len) { - size_t pos; - const uint8_t *ptr = buffer; - int retval; - - for (pos = 0U; pos < len; pos += retval) { - size_t n = len - pos; - retval = (int) send(*sock, &ptr[pos], (int) n, 0); - if (retval <= 0) { - return errno_sock; - } - } - return 0; -} - -int net_init(void) { -#ifdef WIN32 - int r; - WORD wVersionRequested; - WSADATA wsaData; - wVersionRequested = MAKEWORD(2, 2); - if ((r = WSAStartup(wVersionRequested, &wsaData))) { - fprintf(stderr, "WSAStartup failed with error: %d\n", r); - return r; - } - if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { - fprintf(stderr, "Could not find a usable version of Winsock.dll\n"); - WSACleanup(); - return 1; - } -#endif - return 0; -} - -void net_close(const SOCKET *sock) { - closesocket(*sock); -} - -#ifdef WIN32 -static __declspec( thread ) LPTSTR err_buf = NULL; -#else -static _Thread_local char err_buf[1024]; -#endif - -void net_free(void) { -#ifdef WIN32 - WSACleanup(); - if (err_buf) { - LocalFree(err_buf); - err_buf = NULL; - } -#endif -} - -char *net_strerror(int errnum) { -#ifdef WIN32 - if (err_buf) { - LocalFree(err_buf); - err_buf = NULL; - } - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - errnum, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &err_buf, - 0, - NULL); - if (!err_buf) { - return "Unknown error"; - } -#else - int r; - if ((r = strerror_r(errnum, err_buf, sizeof(err_buf) / sizeof(char)))) { - snprintf(err_buf, 1024, "%d (%d)", errnum, r); - } -#endif - return err_buf; -} \ No newline at end of file diff --git a/client/libacron/apps/helloworld/net.h b/client/libacron/apps/helloworld/net.h deleted file mode 100644 index 1a49709..0000000 --- a/client/libacron/apps/helloworld/net.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Created by yuuta on 7/23/22. - */ - -#ifndef ACRONC_NET_H -#define ACRONC_NET_H - -#include -#include - -#ifdef WIN32 -#include - -#else - -#define SOCKET int - -#endif - -#define NET_CLOSED -2 -#define NET_TIMEOUT -1 - -int net_connect(const char *host, - uint16_t port, - SOCKET *sock); - -int net_read(const SOCKET *sock, - void *buffer, - size_t length, - size_t *read, - unsigned int timeout); - -int net_send(const SOCKET *sock, - const void *buffer, - size_t len); - -void net_close(const SOCKET *sock); - -int net_init(void); - -void net_free(void); - -char *net_strerror(int errnum); - -#endif /* ACRONC_NET_H */ -- cgit v1.2.3