]> PatchyGit - patchyircd.git/commitdiff
add VERSION/ADMIN/LUSERS/TIME
authorEgor <egor@patchysicp.xyz>
Wed, 11 May 2022 12:12:39 +0000 (15:12 +0300)
committerEgor <egor@patchysicp.xyz>
Wed, 11 May 2022 12:12:39 +0000 (15:12 +0300)
config.h
irc.c
irc.h
ircfmt.c
ircfmt.h
main.c

index 45ff1f9..7b990e9 100644 (file)
--- a/config.h
+++ b/config.h
@@ -5,3 +5,12 @@
 #define SUPPORT_IPV4
 #define SUPPORT_IPV6
 #define MAX_NICKLEN 32
+#ifndef ADMINLOC1
+#define ADMINLOC1 "Location 1"
+#endif
+#ifndef ADMINLOC2
+#define ADMINLOC2 "Location 2"
+#endif
+#ifndef ADMINEMAIL
+#define ADMINEMAIL "admin@example.com"
+#endif
diff --git a/irc.c b/irc.c
index e8ded31..72f8f20 100644 (file)
--- a/irc.c
+++ b/irc.c
@@ -240,9 +240,6 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                        abort();
                // Send welcome
                newUser(client);
-       } else if(strcmp(command, "MOTD") == 0) {
-               // Send welcome
-               sendMOTD(client);
        } else if(strcmp(command, "OPER") == 0) {
                if (!is_registered(client))
                        return err_notregistered(client), sendbuf(client), 0;
@@ -404,6 +401,40 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                return 1;
        } else if(strcmp(command, "PONG") == 0) {
                // Do nothing
+       // Server Queries and Commands
+       } else if(strcmp(command, "MOTD") == 0) {
+               if (!is_registered(client))
+                       return err_notregistered(client), sendbuf(client), 0;
+               if (args[0] && strcmp(args[0], hostname) != 0)
+                       return err_nosuchserver(client, args[0]), sendbuf(client), 0;
+               // Send welcome
+               sendMOTD(client);
+       } else if(strcmp(command, "VERSION") == 0) {
+               if (!is_registered(client))
+                       return err_notregistered(client), sendbuf(client), 0;
+               if (args[0] && strcmp(args[0], hostname) != 0)
+                       return err_nosuchserver(client, args[0]), sendbuf(client), 0;
+               rpl_version(client, "v0.0.1", "PatchyIRCD v0.0.1"), sendbuf(client);
+               rpl_isupport(client), sendbuf(client);
+       } else if(strcmp(command, "ADMIN") == 0) {
+               if (!is_registered(client))
+                       return err_notregistered(client), sendbuf(client), 0;
+               if (args[0] && strcmp(args[0], hostname) != 0)
+                       return err_nosuchserver(client, args[0]), sendbuf(client), 0;
+               rpl_adminme(client), sendbuf(client);
+               rpl_adminloc1(client, ADMINLOC1), sendbuf(client);
+               rpl_adminloc2(client, ADMINLOC2), sendbuf(client);
+               rpl_adminemail(client, ADMINEMAIL), sendbuf(client);
+       } else if(strcmp(command, "LUSERS") == 0) {
+               if (!is_registered(client))
+                       return err_notregistered(client), sendbuf(client), 0;
+               sendLUSERS(client);
+       } else if(strcmp(command, "TIME") == 0) {
+               if (!is_registered(client))
+                       return err_notregistered(client), sendbuf(client), 0;
+               if (args[0] && strcmp(args[0], hostname) != 0)
+                       return err_nosuchserver(client, args[0]), sendbuf(client), 0;
+               rpl_time(client, get_time()), sendbuf(client);
        } else if(strcmp(command, "MODE") == 0) {
                if (!is_registered(client))
                        return err_notregistered(client), sendbuf(client), 0;
@@ -698,6 +729,7 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                        append_str(&databuf, "\r\n");
                }
                sendbuf(client);
+       // User-Based Queries
        } else if(strcmp(command, "WHO") == 0) {
                if (!is_registered(client))
                        return err_notregistered(client), sendbuf(client), 0;
@@ -816,14 +848,43 @@ void newUser(struct client_data *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);
-       sendbuf(client);
-       copy_strf(&databuf, ":%s 252 %s :Jannies don't exist\n", hostname, client->nick);
-       sendbuf(client);
-       copy_strf(&databuf, ":%s 221 %s %s\r\n", hostname, client->nick, format_umodes(client));
-       sendbuf(client);
+       sendLUSERS(client);
+       rpl_umodeis(client),  sendbuf(client);
        sendMOTD(client);
 }
+void sendLUSERS(struct client_data *client)
+{
+       int total = 0;
+       int registered = 0;
+       int invisible = 0;
+       int ops = 0;
+       int channels = 0;
+       struct trie_find *f = NULL;
+       if (trie_findfirst(&f, &client_map) == 1)
+               do {
+                       struct client_data *cl = f->n->value;
+                       registered++;
+                       if (cl->umode & UMODE_INVISIBLE)
+                               invisible++;
+                       if (cl->umode & UMODE_OPER)
+                               ops++;
+               } while (trie_findnext(&f) == 1);
+       if (trie_findfirst(&f, &client_map) == 1)
+               do {
+                       channels++;
+               } while (trie_findnext(&f) == 1);
+       for (int i = 0; i < CLIENTS; i++)
+               if (clients[i])
+                       total++;
+
+       rpl_luserclient(client, registered, invisible, 1), sendbuf(client);
+       rpl_luserop(client, ops), sendbuf(client);
+       rpl_luserunknown(client, total-registered), sendbuf(client);
+       rpl_luserchannels(client, channels), sendbuf(client);
+       rpl_luserme(client, registered, 0), sendbuf(client);
+       rpl_localusers(client, registered, CLIENTS), sendbuf(client);
+       rpl_globalusers(client, registered, CLIENTS), sendbuf(client);
+}
 
 void sendMOTD(struct client_data *client) {
        copy_strf(&databuf, ":%s 375 %s :PatchySICP /MOTD\n", hostname, client->nick);
diff --git a/irc.h b/irc.h
index 95df9ce..f9100b9 100644 (file)
--- a/irc.h
+++ b/irc.h
@@ -8,6 +8,7 @@
 int parsePacket(struct client_data *client);
 int processPacket(struct client_data *client, char *source, char *command, int argc, char *args[]);
 void newUser(struct client_data *client);
+void sendLUSERS(struct client_data *client);
 void sendMOTD(struct client_data *client);
 void setNick(struct client_data *client, char* nickname);
 struct client_data *findClient(const char *nickname);
index 73bb403..2bb239b 100644 (file)
--- a/ircfmt.c
+++ b/ircfmt.c
@@ -1,6 +1,8 @@
 #include "ircfmt.h"
 extern struct dynarr databuf;
 extern const char *hostname;
+extern const char *format_umodes(struct client_data *cl);
+
 void msg_nick(struct client_data *src, const char *newnick)
 {
        copy_strf(&databuf, ":%s!%s@%s NICK %s\r\n",
@@ -105,20 +107,79 @@ void rpl_isupport(struct client_data *client) // 005
        copy_strf(&databuf, ":%s 005 %s CASEMAPPING=rfc1459 NICKLEN=%u EXCEPTS=e INVEX=I MAXTARGETS=1 CHANMODES=beI,k,l,Pimnst CHANTYPES=#& PREFIX=(ov)@+ STATUSMSG=@+ :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
+#if 0
+void rpl_bounce(struct client_data *client, const char *host, const char *port, const char *info) // 010
+{
+       copy_strf(&databuf, ":%s 010 %s %s %s :%s\r\n",
+                       hostname, client->nick, host, port, info);
+}
+#endif
+void rpl_umodeis(struct client_data *client) // 221
+{
+       copy_strf(&databuf, ":%s 221 %s %s\r\n", hostname, client->nick, format_umodes(client));
+}
+void rpl_luserclient(struct client_data *client, int users, int invisible, int servers) // 251
+{
+       copy_strf(&databuf, ":%s 251 %s :There are %u users and %u invisible on %u servers\r\n",
+                       hostname, client->nick, users, invisible, servers);
+}
+void rpl_luserop(struct client_data *client, int ops) // 252
+{
+       copy_strf(&databuf, ":%s 252 %s %u :operator(s) online\r\n",
+                       hostname, client->nick, ops);
+}
+void rpl_luserunknown(struct client_data *client, int unk) // 253
+{
+       copy_strf(&databuf, ":%s 253 %s %u :unknown connection(s)\r\n",
+                       hostname, client->nick, unk);
+}
+void rpl_luserchannels(struct client_data *client, int channels) // 254
+{
+       copy_strf(&databuf, ":%s 254 %s %u :channels formed\r\n",
+                       hostname, client->nick, channels);
+}
+void rpl_luserme(struct client_data *client, int clients, int servers) // 255
+{
+       copy_strf(&databuf, ":%s 255 %s :I have %u clients and %u servers\r\n",
+                       hostname, client->nick, clients, servers);
+}
+void rpl_adminme(struct client_data *client) // 256
+{
+       copy_strf(&databuf, ":%s 256 %s %s :Administrative info\r\n",
+                       hostname, client->nick, hostname);
+}
+void rpl_adminloc1(struct client_data *client, const char *loc) // 257
+{
+       copy_strf(&databuf, ":%s 257 %s :%s\r\n",
+                       hostname, client->nick, loc);
+}
+void rpl_adminloc2(struct client_data *client, const char *loc) // 258
+{
+       copy_strf(&databuf, ":%s 258 %s :%s\r\n",
+                       hostname, client->nick, loc);
+}
+void rpl_adminemail(struct client_data *client, const char *email) // 259
+{
+       copy_strf(&databuf, ":%s 259 %s :%s\r\n",
+                       hostname, client->nick, email);
+}
+#if 0
+void rpl_tryagain(struct client_data *client, const char *command) // 263
+{
+       copy_strf(&databuf, ":%s 263 %s %s :Please wait a while and try again\r\n",
+                       hostname, client->nick, command);
+}
+#endif
+void rpl_localusers(struct client_data *client, int current, int max) // 266
+{
+       copy_strf(&databuf, ":%s 265 %s :Current local users %u, max %u\r\n",
+                       hostname, client->nick, current, max, current, max);
+}
+void rpl_globalusers(struct client_data *client, int current, int max) // 267
+{
+       copy_strf(&databuf, ":%s 266 %s %u %u :Current global users %u, max %u\r\n",
+                       hostname, client->nick, current, max, current, max);
+}
 // 276 RPL_WHOISCERTFP
 // 300 RPL_NONE
 // 301 RPL_AWAY
@@ -166,7 +227,11 @@ void rpl_topicwhotime(struct client_data *client, struct channel *chan) // 333
 // 347 RPL_ENDOFINVEXLIST
 // 348 RPL_EXCEPTLIST
 // 349 RPL_ENDOFEXCEPTLIST
-// 351 RPL_VERSION
+void rpl_version(struct client_data *client, const char *ver, const char *comments) // 351
+{
+       copy_strf(&databuf, ":%s 351 %s %s %s :%s\r\n", hostname, client->nick,
+                       ver, hostname, comments);
+}
 int rpl_namreply(struct client_data *client, struct channel *chan, struct client_data *cl) // 353
 {
        if (!cl) {
@@ -216,6 +281,14 @@ void rpl_endofnames(struct client_data *client, const char *channel) // 366
 // 381 RPL_YOUREOPER
 // 382 RPL_REHASHING
 // 391 RPL_TIME
+void rpl_time(struct client_data *client, time_t ts) // 391
+{
+       // FIXME: 64-bit time_t support
+       char buf[26];
+       strcpy(buf, ctime(&ts));
+       buf[24] = '\0';
+       copy_strf(&databuf, ":%s 391 %s %s :%s\r\n", hostname, client->nick, ts, buf);
+}
 #if 0
 void err_unknownerror(struct client_data *client, const char *command, const char *msg) // 400
 {
@@ -226,12 +299,10 @@ void err_nosuchnick(struct client_data *client, const char *nick) // 401
 {
        copy_strf(&databuf, ":%s 401 %s %s :No such nick/channel\r\n", hostname, client->nick, nick);
 }
-#if 0
 void err_nosuchserver(struct client_data *client, const char *server) // 402
 {
        copy_strf(&databuf, ":%s 402 %s %s :No such server\r\n", hostname, client->nick, server);
 }
-#endif
 void err_nosuchchannel(struct client_data *client, const char *channel) // 403
 {
        copy_strf(&databuf, ":%s 403 %s %s :No such channel\r\n", hostname, client->nick, channel);
index 91a88f0..cb68b00 100644 (file)
--- a/ircfmt.h
+++ b/ircfmt.h
@@ -20,20 +20,20 @@ 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
+void rpl_bounce(struct client_data *client, const char *host, const char *port, const char *info); // 010
+void rpl_umodeis(struct client_data *client); // 221
+void rpl_luserclient(struct client_data *client, int users, int invisible, int servers); // 251
+void rpl_luserop(struct client_data *client, int ops); // 252
+void rpl_luserunknown(struct client_data *client, int unk); // 253
+void rpl_luserchannels(struct client_data *client, int channels); // 254
+void rpl_luserme(struct client_data *client, int clients, int servers); // 255
+void rpl_adminme(struct client_data *client); // 256
+void rpl_adminloc1(struct client_data *client, const char *loc); // 257
+void rpl_adminloc2(struct client_data *client, const char *loc); // 258
+void rpl_adminemail(struct client_data *client, const char *email); // 259
+void rpl_tryagain(struct client_data *client, const char *command); // 263
+void rpl_localusers(struct client_data *client, int current, int max); // 266
+void rpl_globalusers(struct client_data *client, int current, int max); // 267
 // 276 RPL_WHOISCERTFP
 // 300 RPL_NONE
 // 301 RPL_AWAY
@@ -68,7 +68,7 @@ void rpl_topicwhotime(struct client_data *client, struct channel *chan); // 333
 // 347 RPL_ENDOFINVEXLIST
 // 348 RPL_EXCEPTLIST
 // 349 RPL_ENDOFEXCEPTLIST
-// 351 RPL_VERSION
+void rpl_version(struct client_data *client, const char *ver, const char *comments); // 351
 int rpl_namreply(struct client_data *client, struct channel *chan, struct client_data *cl); // 353
 void rpl_endofnames(struct client_data *client, const char *channel); // 366
 // 364 RPL_LINKS
@@ -85,7 +85,7 @@ void rpl_endofnames(struct client_data *client, const char *channel); // 366
 // 379 RPL_WHOISMODES
 // 381 RPL_YOUREOPER
 // 382 RPL_REHASHING
-// 391 RPL_TIME
+void rpl_time(struct client_data *client, time_t ts); // 391
 void err_unknownerror(struct client_data *client, const char *command, const char *msg); // 400
 void err_nosuchnick(struct client_data *client, const char *nick); // 401
 void err_nosuchserver(struct client_data *client, const char *server); // 402
diff --git a/main.c b/main.c
index e6f8262..fe2638f 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,3 +1,4 @@
+#include <locale.h>
 #include "common.h"
 #include "net.h"
 #include "irc.h"
@@ -182,6 +183,7 @@ int main() {
        SOCKET listeners[4];
        struct tls *listeners_tls[4];
        int listener_count = 0;
+       setlocale(LC_ALL, "C");
        puts("[PatchyIRCD]: Starting up...");
        fflush(stdout);
 
@@ -228,6 +230,7 @@ int main() {
                return fprintf(stderr, "tls_server error\n"), 1;
        if (tls_configure(tls_ctx, tls_cfg) == -1)
                return fprintf(stderr, "tls_configure: %s\n", tls_error(tls_ctx)), 1;
+       tls_config_free(tls_cfg);
 
 #ifdef SUPPORT_IPV4
        serverAddrV4.sin_port = htons(LISTENING_PORT_TLS);