diff options
author | Alec Murphy <alec@checksum.fail> | 2019-09-30 14:37:23 -0400 |
---|---|---|
committer | Alec Murphy <alec@checksum.fail> | 2019-09-30 14:37:23 -0400 |
commit | 8c13bc31adec38de0a4752791054c7301c80fe1b (patch) | |
tree | 32192878fa18916e1caa2d95a8db6ef3022884c6 | |
parent | eba0f00d965464e4153fdef15a1563c5a7fd5bb9 (diff) |
Add files to repository
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Arg.HC | 62 | ||||
-rw-r--r-- | Channel.HC | 327 | ||||
-rw-r--r-- | Client.HC | 468 | ||||
-rw-r--r-- | Command.HC | 237 | ||||
-rw-r--r-- | Gihon.HC | 53 | ||||
-rw-r--r-- | Motd.HC | 38 | ||||
-rw-r--r-- | Motd.TXT | 2 | ||||
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | Service.HC | 7 | ||||
-rw-r--r-- | preview.png | bin | 0 -> 35019 bytes |
11 files changed, 1202 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e89346a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +uncrustify.cfg +.vscode/ @@ -0,0 +1,62 @@ +U0 FreeArgs(I64 argc, U8 **argv) +{ + I64 i; + for (i = 0; i < argc; i++) + { + Free(argv[i]); + } + if (argv) + { + Free(argv); + } +} + +U8 **ParseArgs(U8 *str, I64 *argc) +{ // Return argc, argv from str. + Bool quoted = FALSE; + I64 _argc = 0; + U8 **_argv = NULL; + U8 **_tmp = CAlloc(sizeof(U64) * StrLen(str)); + I64 i = 0; + I64 s = 0; + I64 len; + while (i < StrLen(str) + 1) + { + switch (str[i]) + { + case 0: + case ' ': + if (!quoted) + { + len = (str + i)-(str + s - 1); + if (str[i - 1] == '"') + { + len--; + } + if (len - 1) + { + _tmp[_argc] = CAlloc(len); + MemCpy(_tmp[_argc], str + s, len-1); + _argc++; + } + s = i + 1; + } + break; + case '"': + quoted = !quoted; + if (quoted) + { + s = i + 1; + } + break; + default: + break; + } + i++; + } + *argc = _argc; + _argv = CAlloc(sizeof(U64) * _argc); + MemCpy(_argv, _tmp, sizeof(U64) * _argc); + Free(_tmp); + return _argv; +}
\ No newline at end of file diff --git a/Channel.HC b/Channel.HC new file mode 100644 index 0000000..78aa812 --- /dev/null +++ b/Channel.HC @@ -0,0 +1,327 @@ +U0 IrcChannelAdd(U8 *name) +{ + IrcChannel *channel = CAlloc(sizeof(IrcChannel)); + channel->name = StrNew(name); + channel->topic = CAlloc(2048); + channel->users = CAlloc(sizeof(IrcUser)); + IrcChannel *channels = channel_head; + while (channels->next) + { + channels = channels->next; + } + channel->prev = channels; + channels->next = channel; + ircd_chans_total++; +} + +U0 IrcChannelDel(IrcChannel *channel) +{ + IrcChannel *prev = channel->prev; + IrcChannel *next = channel->next; + prev->next = next; + next->prev = prev; + //free ircuser list + Free(channel->name); + Free(channel); + ircd_chans_total--; +} + +IrcChannel *IrcGetChanByName(U8 *channame) +{ + IrcChannel *channel = channel_head; + while (channel) + { + if (!StrCmp(channel->name, channame)) return channel; + channel = channel->next; + } + return NULL; +} + +U0 IrcChannelUserAdd(IrcChannel *channel, IrcClient *client, U64 flags=NULL) +{ + IrcUser *user = CAlloc(sizeof(IrcUser)); + IrcUser *users = channel->users; + while (users->next) + { + users = users->next; + } + user->client = client; + user->flags = flags; + user->prev = users; + users->next = user; +} + +U0 IrcChannelUserDel(IrcChannel *channel, IrcClient *client) +{ + IrcUser *users = channel->users->next; + IrcUser *prev = NULL; + IrcUser *next = NULL; + while (users) + { + if (users->client==client) + { + prev=users->prev; + next=users->next; + prev->next = next; + next->prev = prev; + Free(users); + return; + } + users = users->next; + } +} + +U0 IrcChannelTopic(U8 *channame, IrcClient *client, U8 *topic) +{ + U8 *buf = CAlloc(2048); + IrcChannel *channel = IrcGetChanByName(channame); + IrcUser *user; + IrcUser *users; + if (channel) + { + user = channel->users->next; + while (user) + { + if (user->client==client) + { + if (user->flags >= IRCD_USERMODE_o) + { + StrPrint(channel->topic, topic); + users = channel->users->next; + while (users) + { + StrPrint(buf, ":%s!%s@%s TOPIC %s :%s\r\n", client->nick, client->username, + client->host, channame, channel->topic); + FifoI64Ins(users->client->msgs, StrNew(buf)); + users = users->next; + } + } + else + { + StrPrint(buf, ":%s 482 %s %s :You do not have access to change the topic on this channel\r\n", + ircd_hostname, client->username, channame); + FifoI64Ins(client->msgs, StrNew(buf)); + } + Free(buf); + return; + } + user = user->next; + } + } + Free(buf); +} + +U0 IrcChannelJoin(U8 *channame, IrcClient *client) +{ + U64 flags = NULL; + if (channame[0]==':') channame++; // Fix for Revolution IRC client? + IrcChannel *channel = IrcGetChanByName(channame); + if (!channel) + { + IrcChannelAdd(channame); + channel = IrcGetChanByName(channame); + flags = IRCD_USERMODE_q; + } + if (channel) + { + IrcChannelUserAdd(channel, client, flags); + IrcClientJoin(channame, client); + } +} + +U0 IrcChannelKick(U8 *channame, IrcClient *client, U8 *nick, U8 *reason=NULL) +{ + U8 *buf = CAlloc(2048); + IrcChannel *channel = IrcGetChanByName(channame); + IrcClient *kick_client = IrcGetClientByNick(nick); + IrcUser *user; + IrcUser *users; + if (channel && kick_client) + { + user = channel->users->next; + while (user) + { + if (user->client==client) + { + if (user->flags >= IRCD_USERMODE_h) + { + users = channel->users->next; + while (users) + { + StrPrint(buf, ":%s!%s@%s KICK %s %s :%s\r\n", client->nick, client->username, + client->host, channame, nick, reason); + FifoI64Ins(users->client->msgs, StrNew(buf)); + users = users->next; + } + IrcChannelUserDel(channel, kick_client); + } + else + { + StrPrint(buf, ":%s 482 %s %s :You must be a channel half-operator\r\n", + ircd_hostname, client->username, channame); + FifoI64Ins(client->msgs, StrNew(buf)); + } + Free(buf); + return; + } + user = user->next; + } + } + Free(buf); +} + +U0 IrcChannelMode(U8 *channame, IrcClient *client, U8 *mode, U8 *nick=NULL) +{ + U64 res = 0; + Bool set = FALSE; + U8 *buf = CAlloc(2048); + IrcChannel *channel = IrcGetChanByName(channame); + IrcClient *mode_client = NULL; + IrcUser *user; + IrcUser *users; + if (nick) + { // Set user mode + mode_client = IrcGetClientByNick(nick); + if (!mode_client) + { + // nick does not exist? + Free(buf); + return; + } + else + { + user = channel->users->next; + while (user) + { + if (user->client==client) + { + if ((!StrCmp("-v", mode) || !StrCmp("+v", mode))) + { + set = TRUE; + if (user->flags < IRCD_USERMODE_h) + { + res = IRCD_USERMODE_h; + } + } + if ((!StrCmp("-h", mode) || !StrCmp("+h", mode))) + { + set = TRUE; + if (user->flags < IRCD_USERMODE_o) + { + res = IRCD_USERMODE_o; + } + } + if ((!StrCmp("-o", mode) || !StrCmp("+o", mode))) + { + set = TRUE; + if (user->flags < IRCD_USERMODE_q) + { + res = IRCD_USERMODE_q; + } + } + + if (set) + { + if (!res) + { + users = channel->users->next; + while (users) + { + if (users->client==mode_client) + { + if (mode[0]=='-') + { + if (user->flags > users->flags) + { + users->flags = NULL; + } + } + if (mode[0]=='+') + { + switch (mode[1]) + { + case 'v': + users->flags = Max(users->flags, IRCD_USERMODE_v); + break; + case 'h': + users->flags = Max(users->flags, IRCD_USERMODE_h); + break; + case 'o': + users->flags = Max(users->flags, IRCD_USERMODE_o); + break; + default: + break; + } + } + } + StrPrint(buf, ":%s!%s@%s MODE %s %s %s\r\n", client->nick, client->username, + client->host, channame, mode, nick); + FifoI64Ins(users->client->msgs, StrNew(buf)); + users = users->next; + } + } + else + { + switch (res) + { + case IRCD_USERMODE_h: + StrPrint(buf, ":%s 482 %s %s :You must have channel halfop access or above to set channel mode #\r\n", + ircd_hostname, client->username, channame); + buf[StrLen(buf)-3] = mode[1]; + FifoI64Ins(client->msgs, StrNew(buf)); + break; + case IRCD_USERMODE_o: + StrPrint(buf, ":%s 482 %s %s :You must have channel op access or above to set channel mode #\r\n", + ircd_hostname, client->username, channame); + buf[StrLen(buf)-3] = mode[1]; + FifoI64Ins(client->msgs, StrNew(buf)); + break; + case IRCD_USERMODE_q: + StrPrint(buf, ":%s 482 %s %s :You must be the channel owner to set channel mode #\r\n", + ircd_hostname, client->username, channame); + buf[StrLen(buf)-3] = mode[1]; + FifoI64Ins(client->msgs, StrNew(buf)); + break; + default: + break; + } + } + } + Free(buf); + return; + } + user = user->next; + } + } + } + else + { // TODO: Set channel mode + if (channel) + { + + } + + } + Free(buf); +} + +U0 IrcChannelPart(U8 *channame, IrcClient *client, U8 *msg=NULL) +{ + IrcChannel *channel = IrcGetChanByName(channame); + if (channel) + { + IrcChannelUserDel(channel, client); + IrcClientPart(channame, client, msg); + } +} + +U0 IrcChannelsQuit(IrcClient *client, U8 *msg=NULL) +{ + IrcChannel *channel = channel_head->next; + while (channel) + { + IrcChannelUserDel(channel, client); + IrcClientQuit(channel->name, client, msg); + channel = channel->next; + } +}
\ No newline at end of file diff --git a/Client.HC b/Client.HC new file mode 100644 index 0000000..bc8d561 --- /dev/null +++ b/Client.HC @@ -0,0 +1,468 @@ +#define IRCD_USERMODE_v 0x1 +#define IRCD_USERMODE_h 0x2 +#define IRCD_USERMODE_o 0x4 +#define IRCD_USERMODE_a 0x8 +#define IRCD_USERMODE_q 0x10 + +class IrcClient +{ +IrcClient *prev; +IrcClient *next; +CTcpSocket *s; +U8 *nick; +U8 *username; +U8 *realname; +U8 *server; +U8 *host; +U32 ip; +U8 *vhost; +CFifoI64 *msgs; +I64 idle; +I64 limit; +Bool disconnected; +}; + +class IrcUser +{ +IrcUser *prev; +IrcUser *next; +IrcClient *client; +U64 flags; +}; + +class IrcChannel +{ +IrcChannel *prev; +IrcChannel *next; +U8 *name; +U8 *topic; +IrcUser *users; +}; + +extern U0 IrcParseCommand(IrcClient *client, U8 *str); +extern U0 IrcChannelsQuit(IrcClient *client, U8 *msg=NULL); + +IrcClient *client_head = CAlloc(sizeof(IrcClient)); +IrcChannel *channel_head = CAlloc(sizeof(IrcChannel)); + +U0 IrcClientAdd(IrcClient *client) +{ + IrcClient *clients = client_head; + while (clients->next) + { + clients = clients->next; + } + client->prev = clients; + clients->next = client; + ircd_clients_total++; +} + +U0 IrcClientDel(IrcClient *client) +{ + IrcClient *prev = client->prev; + IrcClient *next = client->next; + prev->next = next; + next->prev = prev; + FifoI64Del(client->msgs); + Free(client); + ircd_clients_total--; +} + +IrcClient *IrcGetClientByNick(U8 *nick) +{ + IrcClient *client = client_head->next; + while (client) + { + if (!StrCmp(client->nick, nick)) return client; + client = client->next; + } + return NULL; +} + +U0 IrcClientSetNick(IrcClient *client, U8 *nick) +{ + I64 i; + U8 *buf = CAlloc(2048); + IrcClient *chk_client = client_head->next; + + // check if in use, owned, forbidden, etc.. + while (chk_client) + { + if (!StrICmp(chk_client->nick, nick)) + { + StrPrint(buf, ":%s 433 %s %s :Nickname is already in use.\r\n", ircd_hostname, client->username, + nick); + FifoI64Ins(client->msgs, StrNew(buf)); + Free(buf); + return; + } + chk_client = chk_client->next; + } + for (i=0; i<service_cnt; i++) + { + if (!StrICmp(service_nick[i], nick)) + { + StrPrint(buf, ":%s 432 %s %s :Invalid nickname: Reserved for Services\r\n", ircd_hostname, client->username, + nick); + FifoI64Ins(client->msgs, StrNew(buf)); + Free(buf); + return; + } + } + + client->nick = StrNew(nick); + AdamLog("** Gihon - log: nick: %s\n", client->nick); + Free(buf); +} + +U0 IrcClientSetUser(IrcClient *client, U8 *username, U8 *host, U8 *server, U8 *realname) +{ + // check user params + client->username = StrNew(username); + client->host = StrNew(host); + client->realname = StrNew(realname); + client->server = StrNew(server); + AdamLog("** Gihon - log: username: %s, host: %s, realname: %s\n", client->username, client->host, client->realname); +} + +U0 IrcClientMotd(IrcClient *client) +{ + I64 i; + U8 *buf = CAlloc(2048); + StrPrint(buf, ":%s 375 %s :-\r\n", ircd_hostname, client->username); + FifoI64Ins(client->msgs, StrNew(buf)); + for (i=0; i<motd_line_cnt; i++) + { + StrPrint(buf, ":%s 372 %s :%s\r\n", ircd_hostname, client->username, motd_lines[i]); + FifoI64Ins(client->msgs, StrNew(buf)); + } + StrPrint(buf, ":%s 376 %s :>\r\n", ircd_hostname, client->username); + FifoI64Ins(client->msgs, StrNew(buf)); + 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); + IrcClient *rx_client = client_head->next; + IrcChannel *rx_channel = channel_head->next; + IrcUser *rx_user; + while (rx_channel) + { + if (!StrCmp(rx_channel->name, dst)) + { //PRIVMSG to channel + rx_user = rx_channel->users->next; + while (rx_user) + { + rx_client = rx_user->client; + StrPrint(buf, ":%s!%s@%s JOIN :%s\r\n", tx_client->nick, tx_client->username, + tx_client->host, dst); + FifoI64Ins(rx_client->msgs, StrNew(buf)); + rx_user = rx_user->next; + } + return; + } + rx_channel = rx_channel->next; + } + Free(buf); +} + +U0 IrcClientNames(IrcClient *client, U8 *dst) +{ + U8 *buf = CAlloc(2048); + U8 *mode = CAlloc(16); + IrcChannel *channel = channel_head->next; + IrcUser *user; + StrPrint(buf, ":%s 353 %s = %s :", ircd_hostname, client->username, dst); + while (channel) + { + if (!StrCmp(channel->name, dst)) + { + user = channel->users->next; + while (user) + { + StrPrint(mode, ""); + if (user->flags & IRCD_USERMODE_q) StrPrint(mode, "@"); + if (user->flags & IRCD_USERMODE_o) StrPrint(mode, "@"); + if (user->flags & IRCD_USERMODE_h) StrPrint(mode, "\%"); + if (user->flags & IRCD_USERMODE_v) StrPrint(mode, "+"); + StrPrint(buf+StrLen(buf), "%s%s ", mode, user->client->nick); + user = user->next; + } + StrPrint(buf+StrLen(buf), "\r\n"); + FifoI64Ins(client->msgs, StrNew(buf)); + StrPrint(buf, ":%s 366 %s %s :End of /NAMES list.\r\n", ircd_hostname, client->username, dst); + FifoI64Ins(client->msgs, StrNew(buf)); + Free(mode); + Free(buf); + return; + } + channel = channel->next; + } + Free(mode); + Free(buf); +} + +U0 IrcClientTopic(IrcClient *client, U8 *dst) +{ + U8 *buf = CAlloc(2048); + IrcChannel *channel = channel_head->next; + while (channel) + { + if (!StrCmp(channel->name, dst)) + { + if (StrLen(channel->topic)) + { + StrPrint(buf, ":%s 332 %s %s :%s\r\n", ircd_hostname, client->username, dst, channel->topic); + FifoI64Ins(client->msgs, StrNew(buf)); + } + Free(buf); + return; + } + channel = channel->next; + } + Free(buf); +} + +U0 IrcClientPart(U8 *dst, IrcClient *tx_client, U8 *msg=NULL) +{ + U8 *buf = CAlloc(2048); + IrcClient *rx_client = client_head->next; + IrcChannel *rx_channel = channel_head->next; + IrcUser *rx_user; + while (rx_channel) + { + if (!StrCmp(rx_channel->name, dst)) + { //PRIVMSG to channel + rx_user = rx_channel->users->next; + while (rx_user) + { + rx_client = rx_user->client; + if (msg) + { + StrPrint(buf, ":%s!%s@%s PART %s :%s\r\n", tx_client->nick, tx_client->username, + tx_client->host, dst, msg); + } + else + { + StrPrint(buf, ":%s!%s@%s PART %s\r\n", tx_client->nick, tx_client->username, + tx_client->host, dst); + } + FifoI64Ins(rx_client->msgs, StrNew(buf)); + rx_user = rx_user->next; + } + return; + } + rx_channel = rx_channel->next; + } + Free(buf); +} + +U0 IrcClientPing(IrcClient *client, U8 *msg) +{ + U8 *buf = CAlloc(2048); + StrPrint(buf, ":%s PONG %s :%s\r\n", ircd_hostname, ircd_hostname, msg); + FifoI64Ins(client->msgs, StrNew(buf)); + Free(buf); +} + +U0 IrcClientPrivMsg(IrcClient *tx_client, U8 *dst, U8 *msg) +{ + U8 *buf = CAlloc(2048); + IrcClient *rx_client = client_head->next; + while (rx_client) + { + if (!StrCmp(rx_client->nick, dst)) + { //PRIVMSG to nick + StrPrint(buf, ":%s!%s@%s PRIVMSG %s :%s\r\n", tx_client->nick, tx_client->username, + tx_client->host, dst, msg); + FifoI64Ins(rx_client->msgs, StrNew(buf)); + Free(buf); + return; + } + rx_client = rx_client->next; + } + IrcChannel *rx_channel = channel_head->next; + IrcUser *rx_user; + while (rx_channel) + { + if (!StrCmp(rx_channel->name, dst)) + { //PRIVMSG to channel + rx_user = rx_channel->users->next; + while (rx_user) + { + rx_client = rx_user->client; + if (!!StrCmp(rx_client->nick, tx_client->nick)) + { + StrPrint(buf, ":%s!%s@%s PRIVMSG %s :%s\r\n", tx_client->nick, tx_client->username, + tx_client->host, dst, msg); + FifoI64Ins(rx_client->msgs, StrNew(buf)); + } + rx_user = rx_user->next; + } + Free(buf); + return; + } + rx_channel = rx_channel->next; + } + Free(buf); +} + +U0 IrcClientQuit(U8 *dst, IrcClient *tx_client, U8 *msg=NULL) +{ + U8 *buf = CAlloc(2048); + IrcClient *rx_client = client_head->next; + IrcChannel *rx_channel = channel_head->next; + IrcUser *rx_user; + while (rx_channel) + { + if (!StrCmp(rx_channel->name, dst)) + { //PRIVMSG to channel + rx_user = rx_channel->users->next; + while (rx_user) + { + rx_client = rx_user->client; + if (msg) + { + StrPrint(buf, ":%s!%s@%s QUIT :%s\r\n", tx_client->nick, tx_client->username, + tx_client->host, msg); + } + else + { + StrPrint(buf, ":%s!%s@%s QUIT\r\n", tx_client->nick, tx_client->username, + tx_client->host); + } + FifoI64Ins(rx_client->msgs, StrNew(buf)); + rx_user = rx_user->next; + } + return; + } + rx_channel = rx_channel->next; + } + Free(buf); +} + +U0 IrcClientWho(IrcClient *client, U8 *dst) +{ + U8 *buf = CAlloc(2048); + IrcChannel *channel = channel_head->next; + IrcUser *user; + while (channel) + { + if (!StrCmp(channel->name, dst)) + { + user = channel->users->next; + while (user) + { + StrPrint(buf, ":%s 352 %s %s %s %s * %s H :0 %s\r\n", ircd_hostname, client->username, dst, + user->client->username, user->client->host, user->client->nick, + user->client->realname); + FifoI64Ins(client->msgs, StrNew(buf)); + user = user->next; + } + StrPrint(buf, ":%s 315 %s %s :End of /WHO list.\r\n", ircd_hostname, client->username, dst); + FifoI64Ins(client->msgs, StrNew(buf)); + Free(buf); + return; + } + channel = channel->next; + } + Free(buf); +} + +U0 IrcClientRxHandler(CTcpSocket *s) +{ + IrcClient *client = CAlloc(sizeof(IrcClient)); + client->s = s; + client->ip = s->local_addr; + client->limit = IRCD_LIMIT_MAX; + client->msgs = FifoI64New(IRCD_TXFIFO_SIZE); + client->idle = cnts.jiffies; + IrcClientAdd(client); + + 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); + //AdamLog(rxbuf); + //AdamLog("\n"); + client->limit--; + if (client->limit) + { + IrcParseCommand(client, rxbuf); + } + else + { + IrcChannelsQuit(client, "Excess flood"); + err = -1; + } + } + client->disconnected = TRUE; + close(client->s); + Free(rxbuf); + AdamLog("** Gihon - Client disconnected: %16X\n", client); +} + +U0 IrcClientTxHandler() +{ + I64 sec = NULL; + CDateStruct ds; + U8 *buf = CAlloc(2048); + I64 msg = NULL; + IrcClient *client; + while (1) + { + client = client_head->next; + while (client) + { + if (client->disconnected) + { + IrcClientDel(client); + client = client_head; + } + client = client->next; + } + + if (sec != ds.sec) + { + client = client_head->next; + while (client) + { + client->limit = Min(IRCD_LIMIT_MAX, client->limit+1); + client = client->next; + } + sec = ds.sec; + } + + client = client_head->next; + while (client) + { + if (client->idle+IRCD_PING_INTERVAL == cnts.jiffies) + { + 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); + Free(msg); + } + client = client->next; + } + Date2Struct(&ds, Now); + Sleep(1); + } +}
\ No newline at end of file diff --git a/Command.HC b/Command.HC new file mode 100644 index 0000000..e4b6788 --- /dev/null +++ b/Command.HC @@ -0,0 +1,237 @@ +#define IRCD_CMD_ADMIN 0 +#define IRCD_CMD_AWAY 1 +#define IRCD_CMD_CNOTICE 2 +#define IRCD_CMD_CPRIVMSG 3 +#define IRCD_CMD_CONNECT 4 +#define IRCD_CMD_DIE 5 +#define IRCD_CMD_ENCAP 6 +#define IRCD_CMD_ERROR 7 +#define IRCD_CMD_HELP 8 +#define IRCD_CMD_INFO 9 +#define IRCD_CMD_INVITE 10 +#define IRCD_CMD_ISON 11 +#define IRCD_CMD_JOIN 12 +#define IRCD_CMD_KICK 13 +#define IRCD_CMD_KILL 14 +#define IRCD_CMD_KNOCK 15 +#define IRCD_CMD_LINKS 16 +#define IRCD_CMD_LIST 17 +#define IRCD_CMD_LUSERS 18 +#define IRCD_CMD_MODE 19 +#define IRCD_CMD_MOTD 20 +#define IRCD_CMD_NAMES 21 +#define IRCD_CMD_NAMESX 22 +#define IRCD_CMD_NICK 23 +#define IRCD_CMD_NOTICE 24 +#define IRCD_CMD_OPER 25 +#define IRCD_CMD_PART 26 +#define IRCD_CMD_PASS 27 +#define IRCD_CMD_PING 28 +#define IRCD_CMD_PONG 29 +#define IRCD_CMD_PRIVMSG 30 +#define IRCD_CMD_QUIT 31 +#define IRCD_CMD_REHASH 32 +#define IRCD_CMD_RESTART 33 +#define IRCD_CMD_RULES 34 +#define IRCD_CMD_SERVER 35 +#define IRCD_CMD_SERVICE 36 +#define IRCD_CMD_SERVLIST 37 +#define IRCD_CMD_SQUERY 38 +#define IRCD_CMD_SQUIT 39 +#define IRCD_CMD_SETNAME 40 +#define IRCD_CMD_SILENCE 41 +#define IRCD_CMD_STATS 42 +#define IRCD_CMD_SUMMON 43 +#define IRCD_CMD_TIME 44 +#define IRCD_CMD_TOPIC 45 +#define IRCD_CMD_TRACE 46 +#define IRCD_CMD_UHNAMES 47 +#define IRCD_CMD_USER 48 +#define IRCD_CMD_USERHOST 49 +#define IRCD_CMD_USERIP 50 +#define IRCD_CMD_USERS 51 +#define IRCD_CMD_VERSION 52 +#define IRCD_CMD_WALLOPS 53 +#define IRCD_CMD_WATCH 54 +#define IRCD_CMD_WHO 55 +#define IRCD_CMD_WHOIS 56 +#define IRCD_CMD_WHOWAS 57 + +#define IRCD_CMDS_MAX 58 + +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_CPRIVMSG] = "CPRIVMSG"; +ircd_commands[IRCD_CMD_CONNECT] = "CONNECT"; +ircd_commands[IRCD_CMD_DIE] = "DIE"; +ircd_commands[IRCD_CMD_ENCAP] = "ENCAP"; +ircd_commands[IRCD_CMD_ERROR] = "ERROR"; +ircd_commands[IRCD_CMD_HELP] = "HELP"; +ircd_commands[IRCD_CMD_INFO] = "INFO"; +ircd_commands[IRCD_CMD_INVITE] = "INVITE"; +ircd_commands[IRCD_CMD_ISON] = "ISON"; +ircd_commands[IRCD_CMD_JOIN] = "JOIN"; +ircd_commands[IRCD_CMD_KICK] = "KICK"; +ircd_commands[IRCD_CMD_KILL] = "KILL"; +ircd_commands[IRCD_CMD_KNOCK] = "KNOCK"; +ircd_commands[IRCD_CMD_LINKS] = "LINKS"; +ircd_commands[IRCD_CMD_LIST] = "LIST"; +ircd_commands[IRCD_CMD_LUSERS] = "LUSERS"; +ircd_commands[IRCD_CMD_MODE] = "MODE"; +ircd_commands[IRCD_CMD_MOTD] = "MOTD"; +ircd_commands[IRCD_CMD_NAMES] = "NAMES"; +ircd_commands[IRCD_CMD_NAMESX] = "NAMESX"; +ircd_commands[IRCD_CMD_NICK] = "NICK"; +ircd_commands[IRCD_CMD_NOTICE] = "NOTICE"; +ircd_commands[IRCD_CMD_OPER] = "OPER"; +ircd_commands[IRCD_CMD_PART] = "PART"; +ircd_commands[IRCD_CMD_PASS] = "PASS"; +ircd_commands[IRCD_CMD_PING] = "PING"; +ircd_commands[IRCD_CMD_PONG] = "PONG"; +ircd_commands[IRCD_CMD_PRIVMSG] = "PRIVMSG"; +ircd_commands[IRCD_CMD_QUIT] = "QUIT"; +ircd_commands[IRCD_CMD_REHASH] = "REHASH"; +ircd_commands[IRCD_CMD_RESTART] = "RESTART"; +ircd_commands[IRCD_CMD_RULES] = "RULES"; +ircd_commands[IRCD_CMD_SERVER] = "SERVER"; +ircd_commands[IRCD_CMD_SERVICE] = "SERVICE"; +ircd_commands[IRCD_CMD_SERVLIST] = "SERVLIST"; +ircd_commands[IRCD_CMD_SQUERY] = "SQUERY"; +ircd_commands[IRCD_CMD_SQUIT] = "SQUIT"; +ircd_commands[IRCD_CMD_SETNAME] = "SETNAME"; +ircd_commands[IRCD_CMD_SILENCE] = "SILENCE"; +ircd_commands[IRCD_CMD_STATS] = "STATS"; +ircd_commands[IRCD_CMD_SUMMON] = "SUMMON"; +ircd_commands[IRCD_CMD_TIME] = "TIME"; +ircd_commands[IRCD_CMD_TOPIC] = "TOPIC"; +ircd_commands[IRCD_CMD_TRACE] = "TRACE"; +ircd_commands[IRCD_CMD_UHNAMES] = "UHNAMES"; +ircd_commands[IRCD_CMD_USER] = "USER"; +ircd_commands[IRCD_CMD_USERHOST] = "USERHOST"; +ircd_commands[IRCD_CMD_USERIP] = "USERIP"; +ircd_commands[IRCD_CMD_USERS] = "USERS"; +ircd_commands[IRCD_CMD_VERSION] = "VERSION"; +ircd_commands[IRCD_CMD_WALLOPS] = "WALLOPS"; +ircd_commands[IRCD_CMD_WATCH] = "WATCH"; +ircd_commands[IRCD_CMD_WHO] = "WHO"; +ircd_commands[IRCD_CMD_WHOIS] = "WHOIS"; +ircd_commands[IRCD_CMD_WHOWAS] = "WHOWAS"; + +I64 IrcMatchCommand(U8 *str) +{ + I64 i; + for (i=0; i<IRCD_CMDS_MAX; i++) + { + if (!StrICmp(str, ircd_commands[i])) return i; + } + return -1; +} + +U0 IrcParseCommand(IrcClient *client, U8 *str) +{ + U8 **argv; + I64 argc = NULL; + I64 cmd = -1; + argv = ParseArgs(str, &argc); + if (argc) + { + AdamLog("** Gihon - Command: %s from Client %16X\n", argv[0], client); + cmd = IrcMatchCommand(argv[0]); + switch (cmd) + { + case IRCD_CMD_JOIN: + if (argc==2) + { + IrcChannelJoin(argv[1], client); + IrcClientTopic(client, argv[1]); + IrcClientNames(client, argv[1]); + } + break; + case IRCD_CMD_KICK: + if (argc>3) + { + IrcChannelKick(argv[1], client, argv[2], StrFirstOcc(str, ":")+1); + } + else + { + IrcChannelKick(argv[1], client, argv[2], argv[2]); + } + break; + case IRCD_CMD_MODE: + if (argc==3) + { + IrcChannelMode(argv[1], client, argv[2]); + } + if (argc==4) + { + IrcChannelMode(argv[1], client, argv[2], argv[3]); + } + break; + case IRCD_CMD_NICK: + if (argc==2) + { + IrcClientSetNick(client, argv[1]); + } + break; + case IRCD_CMD_PART: + if (argc==2) + { + IrcChannelPart(argv[1], client); + } + + if (argc>2) + { + IrcChannelPart(argv[1], client, StrFirstOcc(str, ":")+1); + } + break; + case IRCD_CMD_PING: + if (argc==2) + { + IrcClientPing(client, argv[1]); + } + break; + case IRCD_CMD_PRIVMSG: + if (argc>2) + { + IrcClientPrivMsg(client, argv[1], StrFirstOcc(str, ":")+1); + } + break; + case IRCD_CMD_QUIT: + if (argc==1) + { + IrcChannelsQuit(client); + } + if (argc>1) + { + IrcChannelsQuit(client, StrFirstOcc(str, ":")+1); + } + break; + case IRCD_CMD_TOPIC: + if (argc>2) + { + IrcChannelTopic(argv[1], client, StrFirstOcc(str, ":")+1); + } + break; + case IRCD_CMD_USER: + if (argc>4) + { + IrcClientSetUser(client, argv[1], argv[2], argv[3], StrFirstOcc(str, ":")+1); // for now + IrcClientMotd(client); + } + break; + case IRCD_CMD_WHO: + if (argc==2) + { + IrcClientWho(client, argv[1]); + } + break; + default: + break; + } + FreeArgs(argc, argv); + } + client->idle = cnts.jiffies; +}
\ No newline at end of file diff --git a/Gihon.HC b/Gihon.HC new file mode 100644 index 0000000..e70ee2e --- /dev/null +++ b/Gihon.HC @@ -0,0 +1,53 @@ +#define IRCD_LIMIT_MAX 20 +#define IRCD_PING_INTERVAL 60000 +#define IRCD_PORT 6667 +#define IRCD_RXBUF_SIZE 4096 +#define IRCD_TXBUF_SIZE 4096 +#define IRCD_TXFIFO_SIZE 128 + +U8 *ircd_hostname = "irc.gihon.local"; +I64 ircd_chans_total = 0; +I64 ircd_clients_total = 0; + +#include "Motd"; +#include "Service"; +#include "Arg"; +#include "Client"; +#include "Channel"; +#include "Command"; + +I64 Gihon() +{ + DocClear(adam_task->put_doc); + DocMax(adam_task->put_doc); + WinToTop(adam_task); + while (!my_ip) { Sleep(1); }; // Wait for Netcfg + CTcpSocket *sock = socket(AF_INET, SOCK_STREAM); + if (sock < 0) + return -1; + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(IRCD_PORT); + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(sock, &addr, sizeof(addr)) < 0) { + close(sock); /* Failed to bind to port */ + return -1; + } + I64 error = listen(sock, 1); + if (error < 0) { /* listen: error */ + return -1; + } + Spawn(&IrcClientTxHandler,, "Gihon ClientTxHandler"); + AdamLog("** Gihon - Server started\n"); + while (1) + { + I64 client = accept(sock, 0, 0); + Spawn(&IrcClientRxHandler, client, "Gihon ClientRxHandler"); + Sleep(1); + } + close(sock); + AdamLog("** Gihon - Server exited\n"); + return 0; +} + +Spawn(&Gihon,,"Gihon Server");
\ No newline at end of file @@ -0,0 +1,38 @@ +U8 **ParseMotd(U8 *str, I64 *argc) +{ + I64 _argc = 0; + U8 **_argv = NULL; + U8 **_tmp = CAlloc(sizeof(U64) * StrLen(str)); + I64 i = 0; + I64 s = 0; + I64 len; + while (i < StrLen(str) + 1) + { + switch (str[i]) + { + case 0: + case '\n': + len = (str + i)-(str + s - 1); + if (len - 1) + { + _tmp[_argc] = CAlloc(len); + MemCpy(_tmp[_argc], str + s, len-1); + _argc++; + } + s = i + 1; + break; + default: + break; + } + i++; + } + *argc = _argc; + _argv = CAlloc(sizeof(U64) * _argc); + MemCpy(_argv, _tmp, sizeof(U64) * _argc); + Free(_tmp); + Free(str); + return _argv; +} + +I64 motd_line_cnt; +U8 **motd_lines = ParseMotd(FileRead("Motd.TXT"), &motd_line_cnt);
\ No newline at end of file diff --git a/Motd.TXT b/Motd.TXT new file mode 100644 index 0000000..69e114d --- /dev/null +++ b/Motd.TXT @@ -0,0 +1,2 @@ +This is an example file. +You can edit this file to display the message of the day.
\ No newline at end of file @@ -1,2 +1,8 @@ # gihon IRC Server for TempleOS + +![Gihon](https://raw.githubusercontent.com/obecebo/gihon/master/preview.png?) + +# details + +This is a work in progress. If you know what you're doing (or even if you don't) feel free to clone the repo and mess around. diff --git a/Service.HC b/Service.HC new file mode 100644 index 0000000..85acc30 --- /dev/null +++ b/Service.HC @@ -0,0 +1,7 @@ +I64 service_cnt = 5; +U8 **service_nick = CAlloc(sizeof(U64)*service_cnt); +service_nick[0] = "NickServ"; +service_nick[1] = "ChanServ"; +service_nick[2] = "MemoServ"; +service_nick[3] = "BotServ"; +service_nick[4] = "HostServ";
\ No newline at end of file diff --git a/preview.png b/preview.png Binary files differnew file mode 100644 index 0000000..6f25e7a --- /dev/null +++ b/preview.png |