/* * xF.c: a toothless IRC client frontend * * Copyright (c) 2022, Přemysl Eric Janouch * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #include "config.h" #define PROGRAM_NAME "xF" #include "common.c" #include "xC-proto.c" #include #include #include #include #include // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static struct { bool polling; struct connector connector; int socket; } g; static void on_connector_connecting (void *user_data, const char *address) { (void) user_data; print_status ("connecting to %s...", address); } static void on_connector_error (void *user_data, const char *error) { (void) user_data; print_status ("connection failed: %s", error); } static void on_connector_failure (void *user_data) { (void) user_data; exit_fatal ("giving up"); } static void on_connector_connected (void *user_data, int socket, const char *hostname) { (void) user_data; (void) hostname; g.polling = false; g.socket = socket; } static void protocol_test (const char *host, const char *port) { struct poller poller = {}; poller_init (&poller); connector_init (&g.connector, &poller); g.connector.on_connecting = on_connector_connecting; g.connector.on_error = on_connector_error; g.connector.on_connected = on_connector_connected; g.connector.on_failure = on_connector_failure; connector_add_target (&g.connector, host, port); g.polling = true; while (g.polling) poller_run (&poller); connector_free (&g.connector); struct str s = str_make (); str_pack_u32 (&s, 0); struct relay_command_message m = {}; m.data.hello.command = RELAY_COMMAND_HELLO; m.data.hello.version = RELAY_VERSION; if (!relay_command_message_serialize (&m, &s)) exit_fatal ("serialization failed"); uint32_t len = htonl (s.len - sizeof len); memcpy (s.str, &len, sizeof len); if (errno = 0, write (g.socket, s.str, s.len) != (ssize_t) s.len) exit_fatal ("short send or error: %s", strerror (errno)); char buf[1 << 20] = ""; while (errno = 0, read (g.socket, &len, sizeof len) == sizeof len) { len = ntohl (len); if (errno = 0, read (g.socket, buf, MIN (len, sizeof buf)) != len) exit_fatal ("short read or error: %s", strerror (errno)); struct msg_unpacker r = msg_unpacker_make (buf, len); struct relay_event_message m = {}; if (!relay_event_message_deserialize (&m, &r)) exit_fatal ("deserialization failed"); if (msg_unpacker_get_available (&r)) exit_fatal ("trailing data"); printf ("event: %d\n", m.data.event); relay_event_message_free (&m); } exit_fatal ("short read or error: %s", strerror (errno)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int main (int argc, char *argv[]) { static const struct opt opts[] = { { 'h', "help", NULL, 0, "display this help and exit" }, { 'V', "version", NULL, 0, "output version information and exit" }, { 0, NULL, NULL, 0, NULL } }; struct opt_handler oh = opt_handler_make (argc, argv, opts, "HOST:PORT", "X11 frontend for xC."); int c; while ((c = opt_handler_get (&oh)) != -1) switch (c) { case 'h': opt_handler_usage (&oh, stdout); exit (EXIT_SUCCESS); case 'V': printf (PROGRAM_NAME " " PROGRAM_VERSION "\n"); exit (EXIT_SUCCESS); default: print_error ("wrong options"); opt_handler_usage (&oh, stderr); exit (EXIT_FAILURE); } argc -= optind; argv += optind; if (argc != 1) { opt_handler_usage (&oh, stderr); exit (EXIT_FAILURE); } opt_handler_free (&oh); char *address = xstrdup (argv[0]); const char *port = NULL, *host = tokenize_host_port (address, &port); if (!port) exit_fatal ("missing port number/service name"); // TODO: Actually implement an X11-based user interface. protocol_test (host, port); return 0; }