]> PatchyGit - patchyircd.git/commitdiff
move message/response formatting to ircfmt.c
authorEgor <egor@patchysicp.xyz>
Thu, 5 May 2022 18:31:09 +0000 (21:31 +0300)
committerEgor <egor@patchysicp.xyz>
Thu, 5 May 2022 18:31:09 +0000 (21:31 +0300)
irc.c
ircfmt.c [new file with mode: 0644]
ircfmt.h [new file with mode: 0644]
net.c
net.h

diff --git a/irc.c b/irc.c
index cec4431..e40ece9 100644 (file)
--- a/irc.c
+++ b/irc.c
@@ -1,4 +1,5 @@
 #include "irc.h"
+#include "ircfmt.h"
 
 struct dynarr databuf;
 
@@ -7,8 +8,7 @@ struct trie_node *channel_map = NULL;
 
 const char *hostname = "irc.patchysicp.xyz";
 #define is_registered(cl) ((cl)->nick != 0)
-static void err_notregistered(struct client_data *client) {
-       copy_strf(&databuf, ":%s 451 * :You have not registered\n", hostname);
+void sendbuf(struct client_data *client) {
        send_log(client->FD, databuf.buf, databuf.len, 0);
 }
 int processPacket(struct client_data *client) {
@@ -86,8 +86,8 @@ int processPacket(struct client_data *client) {
        if(strcmp(command, "PING") == 0) {
                if (!args[0]) // FIXME: error message
                        return 0;
-               copy_strf(&databuf, ":%s PONG %s :%s\n", hostname, hostname, args[0]);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               msg_pong(args[0]);
+               sendbuf(client);
        } else if(strcmp(command, "CAP") == 0) {
                if (!args[0]) // FIXME: error message
                        return 0;
@@ -98,18 +98,18 @@ int processPacket(struct client_data *client) {
                if (strcmp(args[0], "LS") == 0) {
                        // at least one client hangs if it doesn't see a known extension
                        copy_strf(&databuf, ":%s CAP * LS :multi-prefix\n", hostname);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                        if (client->regstate != REG_CAPEND || !client->nick || !client->username)
                                client->regstate = REG_CAPLS;
 
                } else if (strcmp(args[0], "LIST") == 0) {
                        copy_strf(&databuf, ":%s CAP * LIST :\n", hostname);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                } else if (strcmp(args[0], "REQ") == 0) {
                        if (!args[1]) // FIXME: error message
                                return 0;
                        copy_strf(&databuf, ":%s CAP * NAK :%s\n", hostname, args[1]);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                } else if (strcmp(args[0], "END") == 0) {
                        if (client->regstate == REG_CAPLS && client->nick && client->username)
                                newUser(client);
@@ -122,9 +122,6 @@ int processPacket(struct client_data *client) {
                if (!args[0]) // FIXME: error message
                        return 0;
                setNick(client, args[0]);
-               if (client->nick)
-                       printf("USER SET NICKNAME %s\n", client->nick);
-               fflush(stdout);
                if (client->regstate != REG_CAPLS && client->nick && client->username)
                        newUser(client);
        } else if(strcmp(command, "USER") == 0) {
@@ -153,7 +150,7 @@ int processPacket(struct client_data *client) {
                sendMOTD(client);
        } else if(strcmp(command, "JOIN") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (!args[0]) // FIXME: error message
                        return 0;
                if (!strcmp(args[0], "0")) {
@@ -172,7 +169,7 @@ int processPacket(struct client_data *client) {
                channel_join(client, args[0], NULL);
        } else if(strcmp(command, "PART") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (!args[0]) // FIXME: error message
                        return 0;
                char *p = strchr(args[0], ','); // TODO: multiple channels
@@ -184,7 +181,7 @@ int processPacket(struct client_data *client) {
                channel_part(client, chan, args[1] ? args[1] : "");
        } else if(strcmp(command, "TOPIC") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (!args[0]) // FIXME: error message
                        return 0;
                struct channel *chan = findChannel(args[0]);
@@ -208,47 +205,47 @@ int processPacket(struct client_data *client) {
                                if (!chan->topic_who) abort();
                                chan->topic_when = time(NULL);
                        }
-                       copy_strf(&databuf, ":%s!%s@%s TOPIC %s :%s\n", client->nick, client->username, client->hostname, chan->name, args[1]);
+                       msg_topic(client, chan);
                        struct trie_find *f = NULL;
                        if (trie_findfirst(&f, &chan->members) == 1)
                                do {
                                        struct client_data *cl = f->n->value;
-                                       send_log(cl->FD, databuf.buf, databuf.len, 0);
+                                       sendbuf(cl);
                                } while (trie_findnext(&f) == 1);
                }
        } else if(strcmp(command, "PRIVMSG") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (argc < 2) // FIXME: error message
                        return 0;
-               copy_strf(&databuf, ":%s!%s@%s PRIVMSG %s :%s\n", client->nick, client->username, client->hostname, args[0], args[1]);
+               (command[0] == 'P' ? msg_privmsg : msg_notice)(client, args[0], args[1]);
                if (args[0][0] == '#' || args[0][0] == '&') {
-                       sendall_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendall_log(client->FD, databuf.buf, databuf.len, 0); // TODO: limit visibility
                } else {
                        struct client_data *cl = findClient(args[0]);
                        if (!cl) {
                                copy_strf(&databuf, ":%s 401 %s %s :No such nick/channel\n", hostname, client->nick, args[0]);
-                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                               sendbuf(client);
                                return 0;
                        } else {
-                               send_log(cl->FD, databuf.buf, databuf.len, 0);
+                               sendbuf(cl);
                                if (cl->away) {
                                        copy_strf(&databuf, ":%s 301 %s %s :%s\n", hostname, client->nick, cl->nick, cl->away);
-                                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                                       sendbuf(client);
                                }
                        }
                }
        // Start GitHub Copilot - this shit actually be copy pasting my code lmao
        } else if(strcmp(command, "QUIT") == 0) {
-               copy_strf(&databuf, ":%s!%s@%s QUIT :%s\n", client->nick, client->username, client->hostname, args[0] ? args[0] : "Client Quit");
-               sendall_log(client->FD, databuf.buf, databuf.len, 0);
+               msg_quit(client, "Quit: ", args[0] ? args[0] : "");
+               sendall_log(client->FD, databuf.buf, databuf.len, 0); // TODO: limit visibility
                killConnection(client, true);
                return 1;
        } else if(strcmp(command, "PONG") == 0) {
                // Do nothing
        } else if(strcmp(command, "MODE") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (argc == 0) // FIXME: error message
                        return 0;
                char *nick = args[0];
@@ -257,7 +254,7 @@ int processPacket(struct client_data *client) {
                                struct client_data *cl = findClient(nick);
                                if (!cl) {
                                        copy_strf(&databuf, ":%s 401 %s %s :No such nick/channel\n", hostname, client->nick, nick);
-                                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                                       sendbuf(client);
                                        return 0;
                                }
                                copy_strf(&databuf, ":%s 221 %s +", hostname, client->nick);
@@ -267,22 +264,22 @@ int processPacket(struct client_data *client) {
                                if (cl->umode & UMODE_REGISTERED) append_str(&databuf, "r");
                                if (cl->umode & UMODE_WALLOPS) append_str(&databuf, "w");
                                append_str(&databuf, "\r\n");
-                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                               sendbuf(client);
                        } else {
                                copy_strf(&databuf, ":%s 324 %s %s +nt\n", hostname, client->nick, nick);
-                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                               sendbuf(client);
                        }
                } else { // set mode
                        if (*nick != '#' && *nick != '&') {
                                struct client_data *cl = findClient(nick);
                                if (!cl) {
                                        copy_strf(&databuf, ":%s 401 %s %s :No such nick/channel\n", hostname, client->nick, nick);
-                                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                                       sendbuf(client);
                                        return 0;
                                }
                                if (client->FD != cl->FD) {
                                        copy_strf(&databuf, ":%s 502 %s :Can't change mode for other users\n", hostname, client->nick);
-                                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                                       sendbuf(client);
                                        return 0;
                                }
                                int off;
@@ -302,11 +299,11 @@ int processPacket(struct client_data *client) {
                                                        copy_strf(&databuf, ":%s MODE %s +i\n", hostname, client->nick);
                                                        cl->umode |= UMODE_INVISIBLE;
                                                }
-                                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                                               sendbuf(client);
                                                break;
                                        default:
                                                copy_strf(&databuf, ":%s 501 %s :Unknown MODE flag\n", hostname, client->nick);
-                                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                                               sendbuf(client);
                                        }
                                        p++;
                                }
@@ -314,17 +311,17 @@ int processPacket(struct client_data *client) {
                                if (argc == 2) { // Type A channel modes
                                        if (!strcmp(args[1], "+b")) {
                                                copy_strf(&databuf, ":%s 368 %s %s :End of channel ban list\n", hostname, client->nick, args[1]);
-                                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                                               sendbuf(client);
                                                return 0;
                                        }
                                        if (!strcmp(args[1], "+e")) {
                                                copy_strf(&databuf, ":%s 349 %s %s :End of channel exception list\n", hostname, client->nick, args[1]);
-                                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                                               sendbuf(client);
                                                return 0;
                                        }
                                        if (!strcmp(args[1], "+I")) {
                                                copy_strf(&databuf, ":%s 347 %s %s :End of Channel Invite Exception List\n", hostname, client->nick, args[1]);
-                                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                                               sendbuf(client);
                                                return 0;
                                        }
                                }
@@ -333,23 +330,23 @@ int processPacket(struct client_data *client) {
                }
        } else if(strcmp(command, "LIST") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                copy_strf(&databuf, ":%s 321 %s Channel :Users  Name\n", hostname, client->nick);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
                struct trie_find *f = NULL;
                if (trie_findfirst(&f, &channel_map) == 1)
                        do {
                                struct channel *chan = f->n->value;
                                copy_strf(&databuf, ":%s 322 %s %s %u :%s\n", hostname, client->nick,
                                                chan->name, chan->member_count, chan->topic ? chan->topic : "");
-                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                               sendbuf(client);
                        } while(trie_findnext(&f) == 1);
                copy_strf(&databuf, ":%s 323 %s :End of /LIST\n", hostname, client->nick);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
        } else if(strcmp(command, "NAMES") == 0) {
                // TODO: actual channel support
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (argc == 0) // FIXME: error message
                        return 0;
                struct trie_find *f = NULL;
@@ -357,13 +354,13 @@ int processPacket(struct client_data *client) {
                        do {
                                struct client_data *cl = f->n->value;
                                copy_strf(&databuf, ":%s 353 %s = %s :%s\n", hostname, client->nick, args[0], cl->nick);
-                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                               sendbuf(client);
                        } while(trie_findnext(&f) == 1);
                copy_strf(&databuf, ":%s 366 %s :End of /NAMES list\n", hostname, client->nick);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
        } else if(strcmp(command, "USERHOST") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (argc == 0) // FIXME: error message
                        return 0;
                copy_strf(&databuf, ":%s 302 %s", hostname, client->nick);
@@ -383,10 +380,10 @@ int processPacket(struct client_data *client) {
                        }
                        append_str(&databuf, "\r\n");
                }
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
        } else if(strcmp(command, "WHO") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (argc == 0) // FIXME: error message
                        return 0;
                struct client_data *cl = findClient(args[0]);
@@ -395,89 +392,83 @@ int processPacket(struct client_data *client) {
                        copy_strf(&databuf, ":%s 352 %s * %s %s %s %s %s%s :1 %s\n",
                                        hostname, client->nick, cl->username, cl->hostname, hostname, cl->nick,
                                        cl->away ? "G" : "H", cl->umode&UMODE_OPER ? "*" : "", cl->realname);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                }
                copy_strf(&databuf, ":%s 315 %s %s :End of WHO list\n", hostname, client->nick, args[0]);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
        } else if(strcmp(command, "WHOIS") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (argc == 0) // FIXME: error message
                        return 0;
                char *nick = args[1] ? args[1] : args[0];
                struct client_data *cl = findClient(nick);
                if (cl) {
                        copy_strf(&databuf, ":%s 311 %s %s %s %s * :%s\n", hostname, client->nick, cl->nick, cl->username, cl->hostname, cl->realname);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                        copy_strf(&databuf, ":%s 312 %s %s %s :Patchy server\n", hostname, client->nick, cl->nick, hostname);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                        if (cl->umode & UMODE_OPER) {
                                copy_strf(&databuf, ":%s 313 %s %s :is an IRC operator\n", hostname, client->nick, cl->nick);
-                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                               sendbuf(client);
                        }
                        if (cl->away) {
                                copy_strf(&databuf, ":%s 301 %s %s :%s\n", hostname, client->nick, cl->nick, cl->away);
-                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                               sendbuf(client);
                        }
                        copy_strf(&databuf, ":%s 318 %s %s :End of /WHOIS list\n", hostname, client->nick, cl->nick);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                } else {
                        copy_strf(&databuf, ":%s 401 %s %s :No such nick/channel\n", hostname, client->nick, nick);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                }
        } else if(strcmp(command, "AWAY") == 0) {
                if (!is_registered(client))
-                       return err_notregistered(client), 0;
+                       return err_notregistered(client), sendbuf(client), 0;
                if (args[0]) {
                        free(client->away);
                        client->away = mystrdup(args[0]);
                        if (!client->away) abort();
                        copy_strf(&databuf, ":%s 306 %s :You have been marked as being away\n", hostname, client->nick);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                } else {
                        free(client->away);
                        client->away = NULL;
                        copy_strf(&databuf, ":%s 305 %s :You are no longer marked as being away\n", hostname, client->nick);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                }
        } else {
 unknown:
                // Inform user of error
                copy_strf(&databuf, ":%s 421 %s :Unknown command %s\n", hostname, client->nick, command);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
-               fflush(stdout);
+               sendbuf(client);
        }
        return 0;
 }
 
 void newUser(struct client_data *client) {
        client->regstate = REG_CAPEND;
-       copy_strf(&databuf, ":%s 001 %s :Welcome to the Patchy Network, %s\n", hostname, client->nick, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
-       copy_strf(&databuf, ":%s 002 %s :Your host is PatchyIRCD, running version 0.0.1\n", hostname, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
-       copy_strf(&databuf, ":%s 003 %s :This server was created when I had cybersex with your mother.\n", hostname, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
-       copy_strf(&databuf, ":%s 004 %s PatchyIRCD 0.0.1 i nt\n", hostname, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
-       copy_strf(&databuf, ":%s 005 %s CASEMAPPING=rfc1459 NICKLEN=%u CHANTYPES=#& PREFIX=(ov)@+ :are supported by this server\n", hostname, client->nick, MAX_NICKLEN-1);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
+       rpl_welcome(client),  sendbuf(client);
+       rpl_yourhost(client), sendbuf(client);
+       rpl_created(client),  sendbuf(client);
+       rpl_myinfo(client),   sendbuf(client);
+       rpl_isupport(client), sendbuf(client);
        copy_strf(&databuf, ":%s 251 %s :This server exists\n", hostname, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
+       sendbuf(client);
        copy_strf(&databuf, ":%s 252 %s :Jannies don't exist\n", hostname, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
+       sendbuf(client);
        sendMOTD(client);
 }
 
 void sendMOTD(struct client_data *client) {
        copy_strf(&databuf, ":%s 375 %s :PatchySICP /MOTD\n", hostname, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
+       sendbuf(client);
        copy_strf(&databuf, ":%s 372 %s :Welcome to Montreal!\n", hostname, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
+       sendbuf(client);
        copy_strf(&databuf, ":%s 372 %s :You are retarded and I will have cybersex with your mom.\n", hostname, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
+       sendbuf(client);
        copy_strf(&databuf, ":%s 376 %s :/MOTD over\n", hostname, client->nick);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
+       sendbuf(client);
 }
 
 void setNick(struct client_data *client, char* nickname) {
@@ -485,14 +476,14 @@ void setNick(struct client_data *client, char* nickname) {
 
        if (strlen(nickname) >= MAX_NICKLEN || nickname[0] == '\0') {
                copy_strf(&databuf, ":%s 432 * %s :Erroneous nickname\n", hostname, nickname);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
                return;
        }
        const char *forbidden = " ,*?!@$:#&.";
        while (*forbidden)
                if (strchr(nickname, *forbidden++)) {
                        copy_strf(&databuf, ":%s 432 * %s :Erroneous nickname\n", hostname, nickname);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                        return;
                }
 
@@ -503,15 +494,15 @@ void setNick(struct client_data *client, char* nickname) {
        if (trie_get(&client_map, key)) {
                // Nickname is already taken
                copy_strf(&databuf, ":%s 443 * %s :Nickname is already in use\n", hostname, nickname);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
                return;
        }
 
        // Update nickname
        if(client->nick) {
                copy_strf(&databuf, ":%s!%s@%s NICK %s\n", client->nick, client->username, client->hostname, nickname);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
-               sendall_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
+               sendall_log(client->FD, databuf.buf, databuf.len, 0); // TODO: limit visibility
                trie_set(&client_map, client->key, NULL, NULL);
                free(client->nick);
                free(client->key);
@@ -532,12 +523,12 @@ void channel_sendtopic(struct client_data *client, struct channel *chan, int joi
 {
        if (chan->topic) {
                copy_strf(&databuf, ":%s 332 %s %s :%s\n", hostname, client->nick, chan->name, chan->topic);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
                copy_strf(&databuf, ":%s 333 %s %s %s %u\n", hostname, client->nick, chan->name, chan->topic_who, (unsigned)chan->topic_when);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
        } else if (!joining) {
                copy_strf(&databuf, ":%s 331 %s %s :No topic is set\n", hostname, client->nick, chan->name);
-               send_log(client->FD, databuf.buf, databuf.len, 0);
+               sendbuf(client);
        }
 }
 void channel_join(struct client_data *client, const char *channel, const char *chankey)
@@ -580,12 +571,12 @@ void channel_join(struct client_data *client, const char *channel, const char *c
                abort();
        chan->member_count++;
        // send JOIN to everyone
-       copy_strf(&databuf, ":%s!%s@%s JOIN :%s\n", client->nick, client->username, client->hostname, chan->name);
+       msg_join(client, chan);
        struct trie_find *f = NULL;
        if (trie_findfirst(&f, &chan->members) == 1)
                do {
                        struct client_data *cl = f->n->value;
-                       send_log(cl->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(cl);
                } while(trie_findnext(&f) == 1);
        // send topic
        channel_sendtopic(client, chan, 1);
@@ -601,23 +592,20 @@ void channel_join(struct client_data *client, const char *channel, const char *c
                        else
                                prefix = "";
                        copy_strf(&databuf, ":%s 353 %s = %s :%s%s\n", hostname, client->nick, chan->name, prefix, cl->nick);
-                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                       sendbuf(client);
                } while(trie_findnext(&f) == 1);
        copy_strf(&databuf, ":%s 366 %s %s :End of /NAMES list\n", hostname, client->nick, chan->name);
-       send_log(client->FD, databuf.buf, databuf.len, 0);
+       sendbuf(client);
 }
 void channel_part(struct client_data *client, struct channel *chan, const char *reason)
 {
        if (reason) {
-               if (*reason)
-                       copy_strf(&databuf, ":%s!%s@%s PART %s :%s\n", client->nick, client->username, client->hostname, chan->name, reason);
-               else
-                       copy_strf(&databuf, ":%s!%s@%s PART %s\n", client->nick, client->username, client->hostname, chan->name);
+               msg_part(client, chan, *reason ? reason : NULL);
                struct trie_find *f = NULL;
                if (trie_findfirst(&f, &chan->members) == 1)
                        do {
                                struct client_data *cl = f->n->value;
-                               send_log(cl->FD, databuf.buf, databuf.len, 0);
+                               sendbuf(cl);
                        } while (trie_findnext(&f) == 1);
        }
        trie_set(&client->channels, chan->key, NULL, NULL);
diff --git a/ircfmt.c b/ircfmt.c
new file mode 100644 (file)
index 0000000..14b5c86
--- /dev/null
+++ b/ircfmt.c
@@ -0,0 +1,228 @@
+#include "ircfmt.h"
+extern struct dynarr databuf;
+extern const char *hostname;
+void msg_nick(struct client_data *src, const char *newnick)
+{
+       copy_strf(&databuf, ":%s!%s@%s NICK %s\r\n",
+                       src->nick, src->username, src->hostname,
+                       newnick);
+}
+#if 0
+void msg_ping(const char *token)
+{
+       copy_strf(&databuf, ":%s PING :%s\r\n", hostname, token);
+}
+#endif
+void msg_pong(const char *token)
+{
+       copy_strf(&databuf, ":%s PONG %s :%s\r\n", hostname, hostname, token);
+}
+void msg_quit(struct client_data *src, const char *prefix, const char *reason)
+{
+       copy_strf(&databuf, ":%s!%s@%s QUIT :%s%s\r\n",
+                       src->nick, src->username, src->hostname, prefix, reason);
+}
+void msg_error(const char *reason)
+{
+       copy_strf(&databuf, ":%s ERROR :%s\r\n", hostname, reason);
+}
+void msg_join(struct client_data *src, struct channel *chan)
+{
+       copy_strf(&databuf, ":%s!%s@%s JOIN %s\r\n",
+                       src->nick, src->username, src->hostname, chan->name);
+}
+void msg_part(struct client_data *src, struct channel *chan, const char *reason)
+{
+       if (reason)
+               copy_strf(&databuf, ":%s!%s@%s PART %s :%s\r\n",
+                               src->nick, src->username, src->hostname, chan->name, reason);
+       else
+               copy_strf(&databuf, ":%s!%s@%s PART %s\r\n",
+                               src->nick, src->username, src->hostname, chan->name);
+}
+void msg_topic(struct client_data *src, struct channel *chan)
+{
+       copy_strf(&databuf, ":%s!%s@%s TOPIC %s :%s\r\n",
+                       src->nick, src->username, src->hostname,
+                       chan->name, chan->topic ? chan->topic : "");
+}
+#if 0
+void msg_invite(struct client_data *src, struct client_data *dst, struct channel *chan)
+{
+       copy_strf(&databuf, ":%s!%s@%s INVITE %s %s\r\n",
+                       src->nick, src->username, src->hostname, dst->nick, chan->name);
+}
+void msg_kick(struct client_data *src, struct client_data *who, struct channel *chan, const char *reason)
+{
+       if (reason)
+               copy_strf(&databuf, ":%s!%s@%s KICK %s %s :%s\r\n",
+                               src->nick, src->username, src->hostname, chan->name, who->nick, reason);
+       else
+               copy_strf(&databuf, ":%s!%s@%s KICK %s %s\r\n",
+                               src->nick, src->username, src->hostname, chan->name, who->nick);
+}
+#endif
+void msg_privmsg(struct client_data *src, const char *dst, const char *msg)
+{
+       copy_strf(&databuf, ":%s!%s@%s PRIVMSG %s :%s\r\n",
+                       src->nick, src->username, src->hostname, dst, msg);
+}
+void msg_notice(struct client_data *src, const char *dst, const char *msg)
+{
+       copy_strf(&databuf, ":%s!%s@%s NOTICE %s :%s\r\n",
+                       src->nick, src->username, src->hostname, dst, msg);
+}
+#if 0
+void msg_kill(struct client_data *src, struct client_data *dst, const char *reason)
+{
+       copy_strf(&databuf, ":%s!%s@%s KILL %s :%s\r\n",
+                       src->nick, src->username, src->hostname, dst->nick, msg);
+}
+void msg_wallops(struct client_data *src, const char *msg)
+{
+       copy_strf(&databuf, ":%s!%s@%s WALLOPS :%s\r\n",
+                       src->nick, src->username, src->hostname, msg);
+}
+#endif
+void rpl_welcome(struct client_data *client) // 001
+{
+       copy_strf(&databuf, ":%s 001 %s :Welcome to the Patchy Network, %s\r\n", hostname, client->nick, client->nick);
+}
+void rpl_yourhost(struct client_data *client) // 002
+{
+       copy_strf(&databuf, ":%s 002 %s :Your host is PatchyIRCD, running version 0.0.1\r\n", hostname, client->nick);
+}
+void rpl_created(struct client_data *client) // 003
+{
+       copy_strf(&databuf, ":%s 003 %s :This server was created when I had cybersex with your mother.\n", hostname, client->nick);
+}
+void rpl_myinfo(struct client_data *client) // 004
+{
+       copy_strf(&databuf, ":%s 004 %s PatchyIRCD 0.0.1 i nt\n", hostname, client->nick);
+}
+void rpl_isupport(struct client_data *client) // 005
+{
+       copy_strf(&databuf, ":%s 005 %s CASEMAPPING=rfc1459 NICKLEN=%u CHANTYPES=#& PREFIX=(ov)@+ :are supported by this server\n", hostname, client->nick, MAX_NICKLEN-1);
+}
+// 010 RPL_BOUNC
+// 221 RPL_UMODEIS
+// 251 RPL_LUSERCLIENT
+// 252 RPL_LUSEROP
+// 253 RPL_LUSERUNKNOWN
+// 254 RPL_LUSERCHANNELS
+// 255 RPL_LUSERME
+// 256 RPL_ADMINME
+// 257 RPL_ADMINLOC1
+// 258 RPL_ADMINLOC2
+// 259 RPL_ADMINEMAIL
+// 263 RPL_TRYAGAIN
+// 265 RPL_LOCALUSERS
+// 266 RPL_GLOBALUSERS
+// 276 RPL_WHOISCERTFP
+// 300 RPL_NONE
+// 301 RPL_AWAY
+// 302 RPL_USERHOST
+// 305 RPL_UNAWAY
+// 306 RPL_NOWAWAY
+// 352 RPL_WHOREPLY
+// 315 RPL_ENDOFWHO
+// 307 RPL_WHOISREGNICK
+// 311 RPL_WHOISUSER
+// 312 RPL_WHOISSERVER
+// 313 RPL_WHOISOPERATOR
+// 314 RPL_WHOWASUSER
+// 317 RPL_WHOISIDLE
+// 318 RPL_ENDOFWHOIS
+// 319 RPL_WHOISCHANNELS
+// 320 RPL_WHOISSPECIAL
+// 321 RPL_LISTSTART
+// 322 RPL_LIST
+// 323 RPL_LISTEND
+// 324 RPL_CHANNELMODEIS
+// 329 RPL_CREATIONTIME
+// 330 RPL_WHOISACCOUNT
+// 331 RPL_NOTOPIC
+// 332 RPL_TOPIC
+// 333 RPL_TOPICWHOTIME
+// 336 RPL_INVITELIST
+// 337 RPL_ENDOFINVITELIST
+// 338 RPL_WHOISACTUALLY
+// 341 RPL_INVITING
+// 346 RPL_INVEXLIST
+// 347 RPL_ENDOFINVEXLIST
+// 348 RPL_EXCEPTLIST
+// 349 RPL_ENDOFEXCEPTLIST
+// 351 RPL_VERSION
+// 353 RPL_NAMREPLY
+// 366 RPL_ENDOFNAMES
+// 364 RPL_LINKS
+// 365 RPL_ENDOFLINKS
+// 367 RPL_BANLIST
+// 368 RPL_ENDOFBANLIST
+// 369 RPL_ENDOFWHOWAS
+// 371 RPL_INFO
+// 374 RPL_ENDOFINFO
+// 375 RPL_MOTDSTART
+// 372 RPL_MOTD
+// 376 RPL_ENDOFMOTD
+// 378 RPL_WHOISHOST
+// 379 RPL_WHOISMODES
+// 381 RPL_YOUREOPER
+// 382 RPL_REHASHING
+// 391 RPL_TIME
+// 400 ERR_UNKNOWNERROR
+// 401 ERR_NOSUCHNICK
+// 402 ERR_NOSUCHSERVER
+// 403 ERR_NOSUCHCHANNEL
+// 404 ERR_CANNOTSENDTOCHAN
+// 405 ERR_TOOMANYCHANNELS
+// 406 ERR_WASSNOSUCHNICK
+// 409 ERR_NOORIGIN
+// 417 ERR_INPUTTOOLONG
+// 421 ERR_UNKNOWNCOMMAND
+// 422 ERR_NOMOTD
+// 432 ERR_ERRONEUSNICKNAME
+// 433 ERR_NICKNAMEINUSE
+// 441 ERR_USERNOTINCHANNEL
+// 442 ERR_NOTONCHANNEL
+// 443 ERR_USERONCHANNEL
+void err_notregistered(struct client_data *client) // 451
+{
+       (void)client;
+       copy_strf(&databuf, ":%s 451 * :You have not registered\r\n", hostname);
+}
+// 461 ERR_NEEDMOREPARAMS
+// 462 ERR_ALREADYREGISTERED
+// 464 ERR_PASWDMISMATCH
+// 465 ERR_YOUREBANNEDCREEP
+// 471 ERR_CHANNELISFULL
+// 472 ERR_UNKNOWNMODE
+// 473 ERR_INVITEONLYCHAN
+// 474 ERR_BANNEDFROMCHAN
+// 475 ERR_BADCHANNELKEY
+// 476 ERR_BADCHANMASK
+// 481 ERR_NOPRIVILEGES
+// 482 ERR_CHANOPRIVSNEEDED
+// 483 ERR_CANTKILLSERVER
+// 491 ERR_NOOPERHOST
+// 501 ERR_UMODEUNKNOWNFLAG
+// 502 ERR_USERSDONTMATCH
+// 524 ERR_HELPNOTFOUND
+// 525 ERR_INVALIDKEY
+// 670 RPL_STARTTLS
+// 671 RPL_WHOISSECURE
+// 691 ERR_STARTTLS
+// 696 ERR_INVALIDMODEPARAM
+// 704 RPL_HELPSTART
+// 705 RPL_HELPTXT
+// 706 RPL_ENDOFHELP
+// 723 ERR_NOPRIVS
+// 900 RPL_LOGGEDIN
+// 901 RPL_LOGGEDOUT
+// 902 ERR_NICKLOCKED
+// 903 RPL_SASLSUCCESS
+// 904 ERR_SASLFAIL
+// 905 ERR_SASLTOOLONG
+// 906 ERR_SASLABORTED
+// 907 ERR_SASLALREADY
+// 908 RPL_SASLMECHS
diff --git a/ircfmt.h b/ircfmt.h
new file mode 100644 (file)
index 0000000..a9bd157
--- /dev/null
+++ b/ircfmt.h
@@ -0,0 +1,141 @@
+#ifndef IRCFMT_H_
+#define IRCFMT_H_
+#include "irc.h"
+void msg_nick(struct client_data *src, const char *newnick);
+void msg_ping(const char *token);
+void msg_pong(const char *token);
+void msg_quit(struct client_data *src, const char *prefix, const char *reason);
+void msg_error(const char *reason);
+void msg_join(struct client_data *src, struct channel *chan);
+void msg_part(struct client_data *src, struct channel *chan, const char *reason);
+void msg_topic(struct client_data *src, struct channel *chan);
+void msg_invite(struct client_data *src, struct client_data *dst, struct channel *chan);
+void msg_kick(struct client_data *src, struct client_data *who, struct channel *chan, const char *reason);
+void msg_privmsg(struct client_data *src, const char *dst, const char *msg);
+void msg_notice(struct client_data *src, const char *dst, const char *msg);
+void msg_kill(struct client_data *src, struct client_data *dst, const char *reason);
+void msg_wallops(struct client_data *src, const char *msg);
+void rpl_welcome(struct client_data *client); // 001
+void rpl_yourhost(struct client_data *client); // 002
+void rpl_created(struct client_data *client); // 003
+void rpl_myinfo(struct client_data *client); // 004
+void rpl_isupport(struct client_data *client); // 005
+// 010 RPL_BOUNC
+// 221 RPL_UMODEIS
+// 251 RPL_LUSERCLIENT
+// 252 RPL_LUSEROP
+// 253 RPL_LUSERUNKNOWN
+// 254 RPL_LUSERCHANNELS
+// 255 RPL_LUSERME
+// 256 RPL_ADMINME
+// 257 RPL_ADMINLOC1
+// 258 RPL_ADMINLOC2
+// 259 RPL_ADMINEMAIL
+// 263 RPL_TRYAGAIN
+// 265 RPL_LOCALUSERS
+// 266 RPL_GLOBALUSERS
+// 276 RPL_WHOISCERTFP
+// 300 RPL_NONE
+// 301 RPL_AWAY
+// 302 RPL_USERHOST
+// 305 RPL_UNAWAY
+// 306 RPL_NOWAWAY
+// 352 RPL_WHOREPLY
+// 315 RPL_ENDOFWHO
+// 307 RPL_WHOISREGNICK
+// 311 RPL_WHOISUSER
+// 312 RPL_WHOISSERVER
+// 313 RPL_WHOISOPERATOR
+// 314 RPL_WHOWASUSER
+// 317 RPL_WHOISIDLE
+// 318 RPL_ENDOFWHOIS
+// 319 RPL_WHOISCHANNELS
+// 320 RPL_WHOISSPECIAL
+// 321 RPL_LISTSTART
+// 322 RPL_LIST
+// 323 RPL_LISTEND
+// 324 RPL_CHANNELMODEIS
+// 329 RPL_CREATIONTIME
+// 330 RPL_WHOISACCOUNT
+// 331 RPL_NOTOPIC
+// 332 RPL_TOPIC
+// 333 RPL_TOPICWHOTIME
+// 336 RPL_INVITELIST
+// 337 RPL_ENDOFINVITELIST
+// 338 RPL_WHOISACTUALLY
+// 341 RPL_INVITING
+// 346 RPL_INVEXLIST
+// 347 RPL_ENDOFINVEXLIST
+// 348 RPL_EXCEPTLIST
+// 349 RPL_ENDOFEXCEPTLIST
+// 351 RPL_VERSION
+// 353 RPL_NAMREPLY
+// 366 RPL_ENDOFNAMES
+// 364 RPL_LINKS
+// 365 RPL_ENDOFLINKS
+// 367 RPL_BANLIST
+// 368 RPL_ENDOFBANLIST
+// 369 RPL_ENDOFWHOWAS
+// 371 RPL_INFO
+// 374 RPL_ENDOFINFO
+// 375 RPL_MOTDSTART
+// 372 RPL_MOTD
+// 376 RPL_ENDOFMOTD
+// 378 RPL_WHOISHOST
+// 379 RPL_WHOISMODES
+// 381 RPL_YOUREOPER
+// 382 RPL_REHASHING
+// 391 RPL_TIME
+// 400 ERR_UNKNOWNERROR
+// 401 ERR_NOSUCHNICK
+// 402 ERR_NOSUCHSERVER
+// 403 ERR_NOSUCHCHANNEL
+// 404 ERR_CANNOTSENDTOCHAN
+// 405 ERR_TOOMANYCHANNELS
+// 406 ERR_WASSNOSUCHNICK
+// 409 ERR_NOORIGIN
+// 417 ERR_INPUTTOOLONG
+// 421 ERR_UNKNOWNCOMMAND
+// 422 ERR_NOMOTD
+// 432 ERR_ERRONEUSNICKNAME
+// 433 ERR_NICKNAMEINUSE
+// 441 ERR_USERNOTINCHANNEL
+// 442 ERR_NOTONCHANNEL
+// 443 ERR_USERONCHANNEL
+void err_notregistered(struct client_data *client); // 451
+// 461 ERR_NEEDMOREPARAMS
+// 462 ERR_ALREADYREGISTERED
+// 464 ERR_PASWDMISMATCH
+// 465 ERR_YOUREBANNEDCREEP
+// 471 ERR_CHANNELISFULL
+// 472 ERR_UNKNOWNMODE
+// 473 ERR_INVITEONLYCHAN
+// 474 ERR_BANNEDFROMCHAN
+// 475 ERR_BADCHANNELKEY
+// 476 ERR_BADCHANMASK
+// 481 ERR_NOPRIVILEGES
+// 482 ERR_CHANOPRIVSNEEDED
+// 483 ERR_CANTKILLSERVER
+// 491 ERR_NOOPERHOST
+// 501 ERR_UMODEUNKNOWNFLAG
+// 502 ERR_USERSDONTMATCH
+// 524 ERR_HELPNOTFOUND
+// 525 ERR_INVALIDKEY
+// 670 RPL_STARTTLS
+// 671 RPL_WHOISSECURE
+// 691 ERR_STARTTLS
+// 696 ERR_INVALIDMODEPARAM
+// 704 RPL_HELPSTART
+// 705 RPL_HELPTXT
+// 706 RPL_ENDOFHELP
+// 723 ERR_NOPRIVS
+// 900 RPL_LOGGEDIN
+// 901 RPL_LOGGEDOUT
+// 902 ERR_NICKLOCKED
+// 903 RPL_SASLSUCCESS
+// 904 ERR_SASLFAIL
+// 905 ERR_SASLTOOLONG
+// 906 ERR_SASLABORTED
+// 907 ERR_SASLALREADY
+// 908 RPL_SASLMECHS
+#endif
diff --git a/net.c b/net.c
index 9ecb584..ffe6220 100644 (file)
--- a/net.c
+++ b/net.c
@@ -1,5 +1,6 @@
 #include "net.h"
 #include "irc.h"
+#include "ircfmt.h"
 #include <stdbool.h>
 
 void sendall_log(SOCKET socket, const char *buffer, size_t length, int flags) {
@@ -52,13 +53,12 @@ void killConnection(struct client_data *cl, bool byChoice) {
 #endif
        // Start GitHub Copilot
        if(!byChoice && cl->nick && cl->username) {
-               copy_strf(&databuf, ":%s!%s@%s QUIT :Has left the building (Forced)\n", cl->nick, cl->username, cl->hostname);
+               msg_quit(cl, "", "Has left the building (Forced)");
                sendall_log(cl->FD, databuf.buf, databuf.len, 0);
        }
        // Send error to client informing them that they will be disconnected
-       // ERROR :Closing Link: NICK ()
-       copy_strf(&databuf, "ERROR :Closing Link: %s ()\n", cl->nick);
-       send_log(cl->FD, databuf.buf, databuf.len, 0);
+       msg_error("Closing Link");
+       sendbuf(cl);
        // End GitHub Copilot
        shutdown(cl->FD, SHUT_RDWR);
        closesocket(cl->FD);
diff --git a/net.h b/net.h
index 0838e90..5edc6d0 100644 (file)
--- a/net.h
+++ b/net.h
@@ -4,6 +4,7 @@
 #include <stdbool.h>
 
 void sendall_log(SOCKET socket, const char *buffer, size_t length, int flags);
+void sendbuf(struct client_data *client);
 struct client_data *allocClient();
 void killConnection(struct client_data *client, bool byChoice);
 void recvProc(struct client_data *cl);