diff options
Diffstat (limited to 'bounce.h')
-rw-r--r-- | bounce.h | 111 |
1 files changed, 79 insertions, 32 deletions
diff --git a/bounce.h b/bounce.h index 6b376ae..a7bad16 100644 --- a/bounce.h +++ b/bounce.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 C. McEnroe <june@causal.agency> +/* Copyright (C) 2019 June McEnroe <june@causal.agency> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,30 +25,46 @@ * covered work. */ +#include <err.h> #include <limits.h> +#include <stdarg.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> +#include <sysexits.h> #include <tls.h> -#ifndef CERTBOT_PATH -#define CERTBOT_PATH "/etc/letsencrypt" -#endif - #ifndef OPENSSL_BIN #define OPENSSL_BIN "openssl" #endif #define SOURCE_URL "https://git.causal.agency/pounce" -#define ORIGIN "irc.invalid" #define BIT(x) x##Bit, x = 1 << x##Bit, x##Bit_ = x##Bit #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) typedef unsigned char byte; +static inline char *seprintf(char *ptr, char *end, const char *fmt, ...) + __attribute__((format(printf, 3, 4))); +static inline char *seprintf(char *ptr, char *end, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int n = vsnprintf(ptr, end - ptr, fmt, ap); + va_end(ap); + if (n < 0) return NULL; + if (n > end - ptr) return end; + return ptr + n; +} + +static inline void set(char **field, const char *value) { + if (*field) free(*field); + *field = strdup(value); + if (!*field) err(EX_OSERR, "strdup"); +} + enum { MessageCap = 8191 + 512 }; enum { ParamCap = 15 }; @@ -61,9 +77,10 @@ struct Message { static inline struct Message parse(char *line) { struct Message msg = {0}; - if (line[0] == '@') msg.tags = 1 + strsep(&line, " "); - if (line[0] == ':') msg.origin = 1 + strsep(&line, " "); + if (line && line[0] == '@') msg.tags = 1 + strsep(&line, " "); + if (line && line[0] == ':') msg.origin = 1 + strsep(&line, " "); msg.cmd = strsep(&line, " "); + if (msg.cmd && !msg.cmd[0]) msg.cmd = NULL; for (size_t i = 0; line && i < ParamCap; ++i) { if (line[0] == ':') { msg.params[i] = &line[1]; @@ -83,7 +100,10 @@ static inline struct Message parse(char *line) { X("causal.agency/consumer", CapConsumer) \ X("causal.agency/passive", CapPassive) \ X("chghost", CapChghost) \ + X("draft/read-marker", CapReadMarker) \ + X("echo-message", CapEchoMessage) \ X("extended-join", CapExtendedJoin) \ + X("extended-monitor", CapExtendedMonitor) \ X("invite-notify", CapInviteNotify) \ X("labeled-response", CapLabeledResponse) \ X("message-tags", CapMessageTags) \ @@ -94,6 +114,7 @@ static inline struct Message parse(char *line) { X("setname", CapSetname) \ X("sts", CapSTS) \ X("userhost-in-names", CapUserhostInNames) \ + X("znc.in/self-message", CapSelfMessage) \ X("", CapUnsupported) enum Cap { @@ -138,23 +159,28 @@ static inline enum Cap capParse(const char *list, const char *values[CapBits]) { static inline const char *capList(enum Cap caps, const char *values[CapBits]) { static char buf[1024]; buf[0] = '\0'; - size_t len = 0; + char *ptr = buf, *end = &buf[sizeof(buf)]; for (size_t i = 0; i < ARRAY_LEN(CapNames); ++i) { if (caps & (1 << i)) { - len += snprintf( - &buf[len], sizeof(buf) - len, - "%s%s%s%s", - (len ? " " : ""), CapNames[i], - (values && values[i] ? "=" : ""), - (values && values[i] ? values[i] : "") + ptr = seprintf( + ptr, end, "%s%s", (ptr > buf ? " " : ""), CapNames[i] ); - if (len >= sizeof(buf)) break; + if (values && values[i]) { + ptr = seprintf(ptr, end, "=%s", values[i]); + } } } return buf; } extern bool verbose; +static inline void +verboseLog(const char *prefix, const char *line, size_t len) { + if (!verbose) return; + if (len && line[len - 1] == '\n') len--; + if (len && line[len - 1] == '\r') len--; + printf("%s %.*s\n", prefix, (int)len, line); +} void ringAlloc(size_t len); void ringProduce(const char *line); @@ -168,14 +194,19 @@ void ringInfo(void); int ringSave(FILE *file); void ringLoad(FILE *file); -void localConfig(FILE *cert, FILE *priv, FILE *ca, bool require); +int localConfig( + const char *cert, const char *priv, const char *ca, bool require +); size_t localBind(int fds[], size_t cap, const char *host, const char *port); size_t localUnix(int fds[], size_t cap, const char *path); -struct tls *localAccept(int *fd, int bind); +int localAccept(struct tls **tls, int bind); extern struct timeval serverQueueInterval; -void serverConfig(bool insecure, const char *cert, const char *priv); +void serverConfig( + bool insecure, const char *trust, const char *cert, const char *priv +); int serverConnect(const char *bindHost, const char *host, const char *port); +void serverPrintCert(void); void serverRecv(void); void serverSend(const char *ptr, size_t len); void serverFormat(const char *format, ...) @@ -183,22 +214,46 @@ void serverFormat(const char *format, ...) void serverEnqueue(const char *format, ...) __attribute__((format(printf, 1, 2))); void serverDequeue(void); +void serverClose(void); +enum Need { + BIT(NeedHandshake), + BIT(NeedNick), + BIT(NeedUser), + BIT(NeedPass), + BIT(NeedCapEnd), +}; +struct Client { + bool remove; + int sock; + struct tls *tls; + time_t time; + time_t idle; + enum Need need; + enum Cap caps; + size_t consumer; + size_t setPos; + char buf[MessageCap]; + size_t len; +}; extern enum Cap clientCaps; +extern char *clientOrigin; extern char *clientPass; extern char *clientAway; -struct Client *clientAlloc(struct tls *tls); +extern char *clientQuit; +struct Client *clientAlloc(int sock, struct tls *tls); void clientFree(struct Client *client); -bool clientError(const struct Client *client); void clientRecv(struct Client *client); void clientSend(struct Client *client, const char *ptr, size_t len); void clientFormat(struct Client *client, const char *format, ...) __attribute__((format(printf, 2, 3))); -size_t clientDiff(const struct Client *client); void clientConsume(struct Client *client); +void clientGetMarker(struct Client *client, const char *target); extern bool stateNoNames; extern enum Cap stateCaps; +extern char *stateAccount; +extern bool stateAway; void stateLogin( const char *pass, enum Cap blind, const char *plain, const char *nick, const char *user, const char *real @@ -209,16 +264,8 @@ void stateSync(struct Client *client); const char *stateNick(void); const char *stateEcho(void); -struct Cert { - int parent; - int target; - char name[NAME_MAX]; -}; -int certOpen(struct Cert *cert, const char *path); -FILE *certFile(const struct Cert *cert); - -const char *configPath(const char **dirs, const char *path); -const char *dataPath(const char **dirs, const char *path); +char *configPath(char *buf, size_t cap, const char *path, int i); +char *dataPath(char *buf, size_t cap, const char *path, int i); FILE *configOpen(const char *path, const char *mode); FILE *dataOpen(const char *path, const char *mode); |