Start X11 and web frontends for xC

For this, we needed a wire protocol.  After surveying available options,
it was decided to implement an XDR-like protocol code generator
in portable AWK.  It now has two backends, per each of:

 - xF, the X11 frontend, is in C, and is meant to be the primary
   user interface in the future.

 - xP, the web frontend, relies on a protocol proxy written in Go,
   and is meant for use on-the-go (no pun intended).

They are very much work-in-progress proofs of concept right now,
and the relay protocol is certain to change.
This commit is contained in:
2022-08-08 04:39:20 +02:00
parent 2160d03794
commit 1639235a48
20 changed files with 2798 additions and 91 deletions

View File

@@ -1,7 +1,7 @@
/*
* common.c: common functionality
*
* Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
* Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@@ -48,6 +48,66 @@ init_openssl (void)
#endif
}
static char *
gai_reconstruct_address (struct addrinfo *ai)
{
char host[NI_MAXHOST] = {}, port[NI_MAXSERV] = {};
int err = getnameinfo (ai->ai_addr, ai->ai_addrlen,
host, sizeof host, port, sizeof port,
NI_NUMERICHOST | NI_NUMERICSERV);
if (err)
{
print_debug ("%s: %s", "getnameinfo", gai_strerror (err));
return xstrdup ("?");
}
return format_host_port_pair (host, port);
}
static bool
accept_error_is_transient (int err)
{
// OS kernels may return a wide range of unforeseeable errors.
// Assuming that they're either transient or caused by
// a connection that we've just extracted from the queue.
switch (err)
{
case EBADF:
case EINVAL:
case ENOTSOCK:
case EOPNOTSUPP:
return false;
default:
return true;
}
}
/// Destructively tokenize an address into a host part, and a port part.
/// The port is only overwritten if that part is found, allowing for defaults.
static const char *
tokenize_host_port (char *address, const char **port)
{
// Unwrap IPv6 addresses in format_host_port_pair() format.
char *rbracket = strchr (address, ']');
if (*address == '[' && rbracket)
{
if (rbracket[1] == ':')
{
*port = rbracket + 2;
return *rbracket = 0, address + 1;
}
if (!rbracket[1])
return *rbracket = 0, address + 1;
}
char *colon = strchr (address, ':');
if (colon)
{
*port = colon + 1;
return *colon = 0, address;
}
return address;
}
// --- To be moved to liberty --------------------------------------------------
// FIXME: in xssl_get_error() we rely on error reasons never being NULL (i.e.,
@@ -74,6 +134,15 @@ xerr_describe_error (void)
return reason;
}
static struct str
str_from_cstr (const char *cstr)
{
struct str self;
self.alloc = (self.len = strlen (cstr)) + 1;
self.str = memcpy (xmalloc (self.alloc), cstr, self.alloc);
return self;
}
static ssize_t
strv_find (const struct strv *v, const char *s)
{