#include "applet.h" #include #include #include #include #include #include #include #include #include #include #include #include static int fd = 0; void *connection = NULL; const char *get_world(enum ac_world world) { switch (world) { case overworld: return "overworld"; case nether: return "nether"; case end: return "end"; default: return "unknown"; } } static void cleanup(void) { if (connection) ac_disconnect(connection, false); if (fd) close(fd); ac_free(); } static void intr(int signum) {} static int on_send(const void *sock, const void *buffer, const 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(fd, &ptr[pos], (int) n, 0); if (retval < 0) { const int e = errno; perror("Cannot write to socket"); return e; } } return 0; } /* Move init to a separate function from main() so we do not need to keep those stack variables all the time. */ static void init(void) { const char *id = getenv("ID"); const char *token = getenv("TOKEN"); if (!id) errx(64, "Required envvar: ID"); if (!token) errx(64, "Required envvar: TOKEN"); atexit(cleanup); int r; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) <= 0) err(errno, "Cannot create socket"); struct in_addr ad = { .s_addr = 127 | 0 << 8 | 0 << 16 | 1 << 24 }; struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(PORT), .sin_addr = ad }; if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) err(errno, "Cannot connect to server"); libac_config_t libac_conf = { .tok = NULL, #ifdef DEBUG .out = stderr, #else .out = NULL #endif }; if ((r = ac_init(&libac_conf))) errx(r, "Cannot start libac: %d.", r); ac_connection_parameters_t param = { .host = "127.0.0.1", .port = PORT, .id = (char *) id, .token = (char *) token, .version = 0, .sock = &fd, .on_send = on_send }; if ((r = ac_connect(param, &connection))) errx(r, "Cannot connect to server: %d.", r); struct sigaction sa; sa.sa_handler = intr; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGINT, &sa, NULL) == -1) err(errno, "Cannot set SIGINT handler."); if (sigaction(SIGTERM, &sa, NULL) == -1) err(errno, "Cannot set SIGTERM handler."); } int main(void) { init(); int r; int bytes; uint8_t buffer[1024U]; ac_obj_t *obj = NULL; bool ready = false; while (1) { if ((bytes = (int) recv(fd, buffer, sizeof(buffer), 0)) <= 0) { if (bytes < 0) { if (errno == EAGAIN) continue; if (errno == EINTR) { printf("Exit.\n"); return 0; } err(errno, "Cannot read from socket"); } errx(1, "Connection aborted"); } size_t pos = 0; size_t read = 0; bool again = false; while (pos < bytes || again) { if (again) { r = ac_receive(connection, NULL, 0, 0, &obj, NULL); again = false; } else { r = ac_receive(connection, buffer, pos, bytes, &obj, &read); pos += read; } if (r == AC_E_AGAIN) { again = true; } else if (r) { errx(r, "Cannot parse server response: %d.", r); } if (!ready) { enum ac_connection_state state; if ((r = ac_get_state(connection, &state))) { errx(r, "Cannot read state: %d.", r); } if (state == AC_STATE_READY) { printf("Connected.\n"); ready = true; continue; } } if (!obj) { continue; } } } }