aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Murphy <alec@checksum.fail>2019-10-06 21:37:37 -0400
committerAlec Murphy <alec@checksum.fail>2019-10-06 21:37:37 -0400
commit601018807a848923516ffd643d3ec2bd1739e4d9 (patch)
tree3fe580a26f1b7782d709ac620f738b8759f2077f
parent8c13bc31adec38de0a4752791054c7301c80fe1b (diff)
Add spinlock, server password
-rw-r--r--Channel.HC14
-rw-r--r--Client.HC64
-rw-r--r--Command.HC32
-rw-r--r--Gihon.HC4
-rw-r--r--Lock.HC24
5 files changed, 120 insertions, 18 deletions
diff --git a/Channel.HC b/Channel.HC
index 78aa812..034abb5 100644
--- a/Channel.HC
+++ b/Channel.HC
@@ -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
diff --git a/Client.HC b/Client.HC
index bc8d561..c73a452 100644
--- a/Client.HC
+++ b/Client.HC
@@ -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);
}
diff --git a/Command.HC b/Command.HC
index e4b6788..387cb83 100644
--- a/Command.HC
+++ b/Command.HC
@@ -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)
{
diff --git a/Gihon.HC b/Gihon.HC
index e70ee2e..e3dc30d 100644
--- a/Gihon.HC
+++ b/Gihon.HC
@@ -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");
diff --git a/Lock.HC b/Lock.HC
new file mode 100644
index 0000000..cf4519b
--- /dev/null
+++ b/Lock.HC
@@ -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);
+}