From 8e629c02b1a12e88110bcda7f0e67c6a74ff9741 Mon Sep 17 00:00:00 2001 From: Luke Bratch Date: Mon, 10 Jun 2019 19:24:24 +0100 Subject: Refactoring - move structs into a separate file structures.h. --- blabouncer.c | 84 +++------------------------------------------------------ structures.h | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 81 deletions(-) create mode 100644 structures.h diff --git a/blabouncer.c b/blabouncer.c index a421bed..e1f2a96 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -45,6 +45,7 @@ #include "config.h" #include "replay.h" #include "logging.h" +#include "structures.h" #define SOURCE_SERVER 0 #define SOURCE_CLIENT 1 @@ -61,22 +62,15 @@ #define SIGINT 2 // SIGINT is signal 2 #define SIGTERM 15 // SIGTERM is signal 15 +// Various important limits - note that several related ones are defined in structures.h + // It seems to be that *message length* is max 512 bytes, but a socket read from at least UnrealIRCd seems to be up to at least 2416 (+1 for null) bytes. // 1208 bytes with OpenSSL, 2416 bytes with plain text. #define MAXRCVSIZE 2417 -#define MAXDATASIZE 513 // max number of bytes we can get at once (RFC2812 says 512, plus one for null terminator) #define MAXCLIENTS 32 // maximum number of clients that can connect to the bouncer at a time #define MAXTOKENS 100 // maximum number of (CRLF or space) separated tokens per server response we expect (TODO - check this is reasonable) (CRLF and spaces just grouped here due to laziness) -#define MAXPONGSIZE 32 // let's assume PING/PONG responses can't be larger than this (TODO - check this [it's totally made up]!) #define MAXCHANNELS 1024 // let's assume 1024 is reasonable for now (it's configured per IRCd) -#define MAXCHANLENGTH 50 // 50 according to RFC 2811 and RFC 2822 -#define MAXCHANUSERS 8192 // Randomly picked (TODO - is there an actual maximum number of users per channel?) -#define MAXNICKLENGTH 64 // Randomly picked (TODO - is there an actual maximum number (ignoring the RFC preference of 9)?) #define MAXRFCNICKLEN 9 // From RFC 1459 -#define MAXUSERNAMELEN 64 // Randomly picked (TODO - is there an actual maximum username length?) -#define MAXREALNAMELEN 128 // Randomly picked (TODO - is there an actual maximum real name length?) -#define MAXPORTLEN 6 // Up to 65535, so 5 characters + 1 for null -#define MAXAUTOCHANLEN 1024 // Randomly picked maximum length of the auto channel list #define SERVERTIMEOUT 300 // How many seconds to wait without hearing from the server before assuming a timeout // Global debug control @@ -86,78 +80,6 @@ char debugpath[PATH_MAX]; // Path to debug file // Set if certain signal (just SIGINT and SIGKILL at time of writing) is received int signum = 0; -struct channel { - char name[MAXCHANLENGTH]; - char topic[MAXDATASIZE]; // TODO - Is there a particular maximum topic length? - char topicwho[MAXNICKLENGTH]; - // TODO - Make this Year 2038 proof - // TODO - Make this an int? It's just going to arrive and leave as a string every time anyway... - char topicwhen[11]; // 32-bit unixtime is up to 10 characters (+1 for null char) We use "0" to mean "not set". - int gotnames; // Have we finished getting the RPL_NAMREPLYs for this channel yet? -}; - -// TODO - Rename this or split into multiple structs since it's no longer strictly just IRCd strings -struct ircdstrings { - char greeting001[MAXDATASIZE]; - char greeting002[MAXDATASIZE]; - char greeting003[MAXDATASIZE]; - char greeting004[MAXDATASIZE]; - char greeting005a[MAXDATASIZE]; - char greeting005b[MAXDATASIZE]; - char greeting005c[MAXDATASIZE]; - char ircdname[MAXDATASIZE]; - char nickuserhost[MAXDATASIZE]; - char ircnick[MAXNICKLENGTH]; - char ircusername[MAXUSERNAMELEN]; - char currentmsg[MAXDATASIZE]; // Holding area for the current server-received IRC message being processed in case it needs building across multiple reads (i.e. a truncated/split message) - char mode[MAXDATASIZE]; - int capmultiprefix; // Whether the server approved our CAP multi-prefix request - int autonicknum; // Number of attempts made at automatically setting a nick if all configured nicks were in use - int lastmessagetime; // The last time we heard from the server - int reconnecting; // Whether or not we're reconnecting due to an earlier disconnection - char oldnick[MAXNICKLENGTH]; // Set temporarily if we end up reconnecting in case we need to tell existing clients about a nick change -}; - -// Structure of settings either to be read from the configuration file or set/changed at runtime -struct settings { - int replayseconds; - char clientport[MAXPORTLEN]; - char ircnick[MAXNICKLENGTH]; // In both settings and ircdstrings as settings is from our file whereas server may change ircdstrings copy - char ircusername[MAXUSERNAMELEN]; // (Is this also true for the username? Can the server change that?) - char ircrealname[MAXREALNAMELEN]; - char autochannels[MAXAUTOCHANLEN]; - char ircserver[HOST_NAME_MAX]; - char ircserverport[MAXPORTLEN]; - char ircserverpassword[MAXDATASIZE - 5]; // -5 for "PASS " - char connectcommand[MAXDATASIZE]; - char conffile[PATH_MAX]; - char certfile[PATH_MAX]; - char keyfile[PATH_MAX]; - int clienttls; - int servertls; - char basedir[PATH_MAX]; - int logging; - int replaylogging; - int debugkeep; - int background; // Whether or not we're running in the background (detached from the terminal as a daemon) -}; - -// Structure of connected clients, their socket/file descriptors, their authentication status, and their OpenSSL structures -struct client { - int fd; // Client socket fd - 0 means not connected, greater than 0 means connected and the value is the fd number (so we know which ones to try to read and send to) - int authed; // Client authentication status - 0 means not authenticated, 1 means authenticated. - SSL *ssl; // OpenSSL structures when using TLS, or faked by casting fd ints to SSL* if not. - TODO - Can we drop one of either "int fd" or "SSL *ssl" now? - int registered; // Whether the client has finished registering with the bouncer - int pendingchannelmode; // Whether the client is waiting to hear back from a "MODE #channel" command - int pendingban; // Whether the client is waiting to hear back from a "MODE #channel b" command - int pendingwho; // Whether the client is waiting to hear back from a "MODE #channel" command - int pendinglist; // Whether the client is waiting to hear back from a "LIST" command - int pendingwhois; // Whether the client is waiting to hear back from a "WHOIS" command - int pendingwhowas; // Whether the client is waiting to hear back from a "WHOWAS" command - int pendingnames; // Count of RPL_NAMREPLYs the client is waiting on. - int pendingcap; // Whether the client is still negotiating IRCv3 CAPabilities. 0 = no, 1 = yes, -1 = just finished (so register them as if they had just sent USER). -}; - // Signal handler // We don't actually do anything in here, the main pselect() notice signals void sighandler(int sig) { diff --git a/structures.h b/structures.h new file mode 100644 index 0000000..34e8896 --- /dev/null +++ b/structures.h @@ -0,0 +1,88 @@ +#ifndef STRUCTURES_H_INCLUDED +#define STRUCTURES_H_INCLUDED + +#include + +#define MAXDATASIZE 513 // max number of bytes we can get at once (RFC2812 says 512, plus one for null terminator) +#define MAXCHANLENGTH 50 // 50 according to RFC 2811 and RFC 2822 +#define MAXNICKLENGTH 64 // Randomly picked (TODO - is there an actual maximum number (ignoring the RFC preference of 9)?) +#define MAXUSERNAMELEN 64 // Randomly picked (TODO - is there an actual maximum username length?) +#define MAXREALNAMELEN 128 // Randomly picked (TODO - is there an actual maximum real name length?) +#define MAXPORTLEN 6 // Up to 65535, so 5 characters + 1 for null +#define MAXAUTOCHANLEN 1024 // Randomly picked maximum length of the auto channel list + +// TODO - Rename this or split into multiple structs since it's no longer strictly just IRCd strings +struct ircdstrings { + char greeting001[MAXDATASIZE]; + char greeting002[MAXDATASIZE]; + char greeting003[MAXDATASIZE]; + char greeting004[MAXDATASIZE]; + char greeting005a[MAXDATASIZE]; + char greeting005b[MAXDATASIZE]; + char greeting005c[MAXDATASIZE]; + char ircdname[MAXDATASIZE]; + char nickuserhost[MAXDATASIZE]; + char ircnick[MAXNICKLENGTH]; + char ircusername[MAXUSERNAMELEN]; + char currentmsg[MAXDATASIZE]; // Holding area for the current server-received IRC message being processed in case it needs building across multiple reads (i.e. a truncated/split message) + char mode[MAXDATASIZE]; + int capmultiprefix; // Whether the server approved our CAP multi-prefix request + int autonicknum; // Number of attempts made at automatically setting a nick if all configured nicks were in use + int lastmessagetime; // The last time we heard from the server + int reconnecting; // Whether or not we're reconnecting due to an earlier disconnection + char oldnick[MAXNICKLENGTH]; // Set temporarily if we end up reconnecting in case we need to tell existing clients about a nick change +}; + +// Structure of settings either to be read from the configuration file or set/changed at runtime +struct settings { + int replayseconds; + char clientport[MAXPORTLEN]; + char ircnick[MAXNICKLENGTH]; // In both settings and ircdstrings as settings is from our file whereas server may change ircdstrings copy + char ircusername[MAXUSERNAMELEN]; // (Is this also true for the username? Can the server change that?) + char ircrealname[MAXREALNAMELEN]; + char autochannels[MAXAUTOCHANLEN]; + char ircserver[HOST_NAME_MAX]; + char ircserverport[MAXPORTLEN]; + char ircserverpassword[MAXDATASIZE - 5]; // -5 for "PASS " + char connectcommand[MAXDATASIZE]; + char conffile[PATH_MAX]; + char certfile[PATH_MAX]; + char keyfile[PATH_MAX]; + int clienttls; + int servertls; + char basedir[PATH_MAX]; + int logging; + int replaylogging; + int debugkeep; + int background; // Whether or not we're running in the background (detached from the terminal as a daemon) +}; + +// Structure of a connected clien, their socket/file descriptors, their authentication status, and their OpenSSL structures +// This struct is expected to be in an array of client structs +struct client { + int fd; // Client socket fd - 0 means not connected, greater than 0 means connected and the value is the fd number (so we know which ones to try to read and send to) + int authed; // Client authentication status - 0 means not authenticated, 1 means authenticated. + SSL *ssl; // OpenSSL structures when using TLS, or faked by casting fd ints to SSL* if not. - TODO - Can we drop one of either "int fd" or "SSL *ssl" now? + int registered; // Whether the client has finished registering with the bouncer + int pendingchannelmode; // Whether the client is waiting to hear back from a "MODE #channel" command + int pendingban; // Whether the client is waiting to hear back from a "MODE #channel b" command + int pendingwho; // Whether the client is waiting to hear back from a "MODE #channel" command + int pendinglist; // Whether the client is waiting to hear back from a "LIST" command + int pendingwhois; // Whether the client is waiting to hear back from a "WHOIS" command + int pendingwhowas; // Whether the client is waiting to hear back from a "WHOWAS" command + int pendingnames; // Count of RPL_NAMREPLYs the client is waiting on. + int pendingcap; // Whether the client is still negotiating IRCv3 CAPabilities. 0 = no, 1 = yes, -1 = just finished (so register them as if they had just sent USER). +}; + +// Structure of a channel - this struct is expected to be in an array of channel structs +struct channel { + char name[MAXCHANLENGTH]; + char topic[MAXDATASIZE]; // TODO - Is there a particular maximum topic length? + char topicwho[MAXNICKLENGTH]; + // TODO - Make this Year 2038 proof + // TODO - Make this an int? It's just going to arrive and leave as a string every time anyway... + char topicwhen[11]; // 32-bit unixtime is up to 10 characters (+1 for null char) We use "0" to mean "not set". + int gotnames; // Have we finished getting the RPL_NAMREPLYs for this channel yet? +}; + +#endif -- cgit v1.2.3