diff options
author | Alec Murphy <alec@checksum.fail> | 2019-10-06 21:37:37 -0400 |
---|---|---|
committer | Alec Murphy <alec@checksum.fail> | 2019-10-06 21:37:37 -0400 |
commit | 601018807a848923516ffd643d3ec2bd1739e4d9 (patch) | |
tree | 3fe580a26f1b7782d709ac620f738b8759f2077f | |
parent | 8c13bc31adec38de0a4752791054c7301c80fe1b (diff) |
Add spinlock, server password
-rw-r--r-- | Channel.HC | 14 | ||||
-rw-r--r-- | Client.HC | 64 | ||||
-rw-r--r-- | Command.HC | 32 | ||||
-rw-r--r-- | Gihon.HC | 4 | ||||
-rw-r--r-- | Lock.HC | 24 |
5 files changed, 120 insertions, 18 deletions
@@ -21,6 +21,8 @@ U0 IrcChannelDel(IrcChannel *channel) prev->next = next; next->prev = prev; //free ircuser list + Free(channel->users); + Free(channel->topic); Free(channel->name); Free(channel); ircd_chans_total--; @@ -154,6 +156,7 @@ U0 IrcChannelKick(U8 *channame, IrcClient *client, U8 *nick, U8 *reason=NULL) users = users->next; } IrcChannelUserDel(channel, kick_client); + if (!channel->users->next) IrcChannelDel(channel); } else { @@ -312,6 +315,7 @@ U0 IrcChannelPart(U8 *channame, IrcClient *client, U8 *msg=NULL) { IrcChannelUserDel(channel, client); IrcClientPart(channame, client, msg); + if (!channel->users->next) IrcChannelDel(channel); } } @@ -324,4 +328,14 @@ U0 IrcChannelsQuit(IrcClient *client, U8 *msg=NULL) IrcClientQuit(channel->name, client, msg); channel = channel->next; } + channel = channel_head->next; + while (channel) + { + if (!channel->users->next) + { + IrcChannelDel(channel); + channel = channel_head; + } + channel = channel->next; + } }
\ No newline at end of file @@ -19,6 +19,9 @@ U8 *vhost; CFifoI64 *msgs; I64 idle; I64 limit; +I64 ping; +Bool auth; +Bool closed; Bool disconnected; }; @@ -45,6 +48,14 @@ extern U0 IrcChannelsQuit(IrcClient *client, U8 *msg=NULL); IrcClient *client_head = CAlloc(sizeof(IrcClient)); IrcChannel *channel_head = CAlloc(sizeof(IrcChannel)); +U0 IrcClientClose(IrcClient *client) +{ + if (client->closed) return; + client->closed = TRUE; + if (client->s->state==TCP_STATE_CLOSING || client->s->state==TCP_STATE_CLOSED) return; + close(client->s); +} + U0 IrcClientAdd(IrcClient *client) { IrcClient *clients = client_head; @@ -64,6 +75,7 @@ U0 IrcClientDel(IrcClient *client) prev->next = next; next->prev = prev; FifoI64Del(client->msgs); + MemSet(client, 0, sizeof(IrcClient)); Free(client); ircd_clients_total--; } @@ -125,8 +137,18 @@ U0 IrcClientSetUser(IrcClient *client, U8 *username, U8 *host, U8 *server, U8 *r AdamLog("** Gihon - log: username: %s, host: %s, realname: %s\n", client->username, client->host, client->realname); } +U0 IrcClientNotice(IrcClient *client, U8 *msg) +{ + U8 *buf = CAlloc(2048); + StrPrint(buf, ":%s NOTICE Auth :%s\r\n", ircd_hostname, msg); + FifoI64Ins(client->msgs, StrNew(buf)); + Free(buf); +} + U0 IrcClientMotd(IrcClient *client) { + IrcClientNotice(client, "Welcome to Gihon IRC Server!"); + IrcClientNotice(client, "This server is running Gihon, an IRCd for TempleOS"); I64 i; U8 *buf = CAlloc(2048); StrPrint(buf, ":%s 375 %s :-\r\n", ircd_hostname, client->username); @@ -141,14 +163,6 @@ U0 IrcClientMotd(IrcClient *client) Free(buf); } -U0 IrcClientNotice(IrcClient *client, U8 *msg) -{ - U8 *buf = CAlloc(2048); - StrPrint(buf, ":%s NOTICE Auth :%s\r\n", ircd_hostname, msg); - FifoI64Ins(client->msgs, StrNew(buf)); - Free(buf); -} - U0 IrcClientJoin(U8 *dst, IrcClient *tx_client) { U8 *buf = CAlloc(2048); @@ -386,16 +400,18 @@ U0 IrcClientRxHandler(CTcpSocket *s) client->limit = IRCD_LIMIT_MAX; client->msgs = FifoI64New(IRCD_TXFIFO_SIZE); client->idle = cnts.jiffies; + if (!ircd_password) client->auth = TRUE; + spin_lock(&spinlock); IrcClientAdd(client); + spin_unlock(&spinlock); AdamLog("** Gihon - Client connected: %16X\n", client); - IrcClientNotice(client, "Welcome to Gihon IRC Server!"); - IrcClientNotice(client, "This server is running Gihon, an IRCd for TempleOS"); I64 err = NULL; U8 *rxbuf = CAlloc(IRCD_RXBUF_SIZE); while (err > -1) { err = recvLine(s, rxbuf, IRCD_RXBUF_SIZE, 0); + spin_lock(&spinlock); //AdamLog(rxbuf); //AdamLog("\n"); client->limit--; @@ -406,11 +422,21 @@ U0 IrcClientRxHandler(CTcpSocket *s) else { IrcChannelsQuit(client, "Excess flood"); - err = -1; + err = -2; } + spin_unlock(&spinlock); + } + if (err == -1) + { + spin_lock(&spinlock); + IrcChannelsQuit(client, "Connection reset by peer"); + spin_unlock(&spinlock); + } + if (!client->disconnected) + { + client->disconnected = TRUE; + IrcClientClose(client); } - client->disconnected = TRUE; - close(client->s); Free(rxbuf); AdamLog("** Gihon - Client disconnected: %16X\n", client); } @@ -424,6 +450,7 @@ U0 IrcClientTxHandler() IrcClient *client; while (1) { + spin_lock(&spinlock); client = client_head->next; while (client) { @@ -451,17 +478,26 @@ U0 IrcClientTxHandler() { if (client->idle+IRCD_PING_INTERVAL == cnts.jiffies) { + client->ping++; + if (client>1) + { + IrcChannelsQuit(client, "Ping timeout"); + // IrcClientClose(client); + client->disconnected = TRUE; + } StrPrint(buf, "PING :%s\r\n", ircd_hostname); FifoI64Ins(client->msgs, StrNew(buf)); } while (FifoI64Cnt(client->msgs)) { FifoI64Rem(client->msgs, &msg); - sendString(client->s, msg, 0); + if (!client->closed) sendString(client->s, msg, 0); Free(msg); } client = client->next; } + spin_unlock(&spinlock); + Date2Struct(&ds, Now); Sleep(1); } @@ -1,6 +1,6 @@ #define IRCD_CMD_ADMIN 0 #define IRCD_CMD_AWAY 1 -#define IRCD_CMD_CNOTICE 2 +#define IRCD_CMD_CAP 2 #define IRCD_CMD_CPRIVMSG 3 #define IRCD_CMD_CONNECT 4 #define IRCD_CMD_DIE 5 @@ -63,7 +63,7 @@ U8 **ircd_commands = CAlloc(sizeof(U64) * IRCD_CMDS_MAX); ircd_commands[IRCD_CMD_ADMIN] = "ADMIN"; ircd_commands[IRCD_CMD_AWAY] = "AWAY"; -ircd_commands[IRCD_CMD_CNOTICE] = "CNOTICE"; +ircd_commands[IRCD_CMD_CAP] = "CAP"; ircd_commands[IRCD_CMD_CPRIVMSG] = "CPRIVMSG"; ircd_commands[IRCD_CMD_CONNECT] = "CONNECT"; ircd_commands[IRCD_CMD_DIE] = "DIE"; @@ -138,10 +138,18 @@ U0 IrcParseCommand(IrcClient *client, U8 *str) argv = ParseArgs(str, &argc); if (argc) { - AdamLog("** Gihon - Command: %s from Client %16X\n", argv[0], client); cmd = IrcMatchCommand(argv[0]); + if (!client->auth && cmd != IRCD_CMD_PASS && cmd != IRCD_CMD_CAP) + { + IrcClientClose(client); + FreeArgs(argc, argv); + return; + } + AdamLog("** Gihon - Command: %s from Client %16X\n", argv[0], client); switch (cmd) { + case IRCD_CMD_CAP: + break; case IRCD_CMD_JOIN: if (argc==2) { @@ -187,12 +195,30 @@ U0 IrcParseCommand(IrcClient *client, U8 *str) IrcChannelPart(argv[1], client, StrFirstOcc(str, ":")+1); } break; + case IRCD_CMD_PASS: + if (argc>1) + { + if (!StrCmp(ircd_password, argv[1])) + { + client->auth = TRUE; + } + else + { + IrcClientClose(client); + FreeArgs(argc, argv); + return; + } + } + break; case IRCD_CMD_PING: if (argc==2) { IrcClientPing(client, argv[1]); } break; + case IRCD_CMD_PONG: + client->ping = Max(0, client->ping-1); + break; case IRCD_CMD_PRIVMSG: if (argc>2) { @@ -6,9 +6,11 @@ #define IRCD_TXFIFO_SIZE 128 U8 *ircd_hostname = "irc.gihon.local"; +U8 *ircd_password = NULL; // server password if you want one I64 ircd_chans_total = 0; I64 ircd_clients_total = 0; +#include "Lock"; #include "Motd"; #include "Service"; #include "Arg"; @@ -50,4 +52,4 @@ I64 Gihon() return 0; } -Spawn(&Gihon,,"Gihon Server");
\ No newline at end of file +Spawn(&Gihon,,"Gihon Server"); @@ -0,0 +1,24 @@ +#define BUSY 1 +#define SPINLOCK_INITIALIZER 0 + +U8 spinlock = SPINLOCK_INITIALIZER; + +U0 spin_lock(U8 *lock) +{ + while (1) { + if (!LXchgU8(lock, BUSY)) return; + + while (*lock) { Sleep(1); } + } +} + +U0 spin_unlock(U8 *lock) +{ + Sleep(RandU16 & 0xFF); + *lock = 0; +} + +U8 spin_trylock(U8 *lock) +{ + return LXchgU8(lock, BUSY); +} |