summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTest_User <hax@andrewyu.org>2023-05-06 03:03:58 -0400
committerTest_User <hax@andrewyu.org>2023-05-06 03:03:58 -0400
commit32d75fadbf193218d0be42ca91b7688f1854f6e4 (patch)
treebacc1c35036a0b38fe63f6cffeb711be43cc7ae3
parent329ca8e8f40efdd7838d40435b5f113d2877c13c (diff)
downloadcoupserv-32d75fadbf193218d0be42ca91b7688f1854f6e4.tar.gz
coupserv-32d75fadbf193218d0be42ca91b7688f1854f6e4.zip
Start adding client support
-rw-r--r--Makefile8
-rw-r--r--client_network.c158
-rw-r--r--config.h2
-rw-r--r--main.c174
-rw-r--r--network.h16
-rw-r--r--server_network.c (renamed from network.c)31
6 files changed, 364 insertions, 25 deletions
diff --git a/Makefile b/Makefile
index 078fdf3..9c832ec 100644
--- a/Makefile
+++ b/Makefile
@@ -30,14 +30,14 @@
CFLAGS += $(INCLUDEFLAGS) -D_REENTRANT -ggdb3 -Wall -Wextra -Wno-unused-parameter $(shell pkg-config gnutls --cflags)
-LDFLAGS = -lssl -lcrypto $(shell pkg-config gnutls --libs)
+LDFLAGS = -lpthread $(shell pkg-config gnutls --libs)
DEPS = $(shell $(CC) $(INCLUDEFLAGS) -MM -MT $(1).o $(1).c | sed -z 's/\\\n //g')
.PHONY: all clean cleanall release
all: haxserv
-haxserv: main.o network.o commands.o table.o config.o tls.o utils.o
+haxserv: main.o server_network.o client_network.o commands.o table.o config.o tls.o utils.o
$(CC) $^ -o $@ $(LDFLAGS)
%.o: %.c
@@ -45,7 +45,9 @@ haxserv: main.o network.o commands.o table.o config.o tls.o utils.o
$(call DEPS,main)
-$(call DEPS,network)
+$(call DEPS,server_network)
+
+$(call DEPS,client_network)
$(call DEPS,commands)
diff --git a/client_network.c b/client_network.c
new file mode 100644
index 0000000..05e0787
--- /dev/null
+++ b/client_network.c
@@ -0,0 +1,158 @@
+// Client network command handlers for HaxServ
+//
+// Written by: Test_User <hax@andrewyu.org>
+//
+// This is free and unencumbered software released into the public
+// domain.
+//
+// Anyone is free to copy, modify, publish, use, compile, sell, or
+// distribute this software, either in source code form or as a compiled
+// binary, for any purpose, commercial or non-commercial, and by any
+// means.
+//
+// In jurisdictions that recognize copyright laws, the author or authors
+// of this software dedicate any and all copyright interest in the
+// software to the public domain. We make this dedication for the benefit
+// of the public at large and to the detriment of our heirs and
+// successors. We intend this dedication to be an overt act of
+// relinquishment in perpetuity of all present and future rights to this
+// software under copyright law.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#include <gnutls/gnutls.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "network.h"
+#include "config.h"
+#include "types.h"
+#include "table.h"
+#include "tls.h"
+
+// TODO: Lock sends (everywhere)
+
+struct table client_network_commands = {0};
+struct string client_nick = {0};
+uint8_t client_connected;
+
+int client_nick_handler(uint64_t argc, struct string *argv) {
+ if (argc < 1)
+ return 1;
+
+ void *tmp = malloc(argv[0].len);
+ if (!tmp)
+ return 1;
+ memcpy(tmp, argv[0].data, argv[0].len);
+
+ free(client_nick.data);
+
+ client_nick.data = tmp;
+ client_nick.len = argv[0].len;
+
+ if (client_connected) {
+ SEND(STRING(":1HC000001 NICK "));
+ SEND(client_nick);
+ SEND(STRING(" "));
+ char current_time[22];
+ snprintf(current_time, 22, "%ld", time(NULL));
+ SEND(((struct string){current_time, strlen(current_time)}));
+ SEND(STRING("\n"));
+ }
+
+ return 0;
+}
+
+int client_user_handler(uint64_t argc, struct string *argv) {
+ if (argc < 4)
+ return 1;
+
+ if (client_nick.len == 0)
+ return 1;
+
+ char current_time[22];
+ snprintf(current_time, 22, "%ld", time(NULL));
+ SEND(STRING("UID 1HC000001 "));
+ SEND(((struct string){current_time, strlen(current_time)}));
+ SEND(STRING(" "));
+ SEND(client_nick);
+ SEND(STRING(" "));
+ SEND(client_hostmask);
+ SEND(STRING(" "));
+ SEND(client_hostmask);
+ SEND(STRING(" "));
+ SEND(argv[0]);
+ SEND(STRING(" 192.168.1.1 "));
+ SEND(((struct string){current_time, strlen(current_time)}));
+ SEND(STRING(" +k :"));
+ SEND(argv[3]);
+ SEND(STRING("\n"));
+
+ SENDCLIENT(STRING(":hax.irc.andrewyu.org 001 me :Welcome to the LibreIRC IRC Network\n"));
+ SENDCLIENT(STRING(":hax.irc.andrewyu.org 002 me :Your host is hax.irc.andrewyu.org, running a totally not sus IRCd\n"));
+ SENDCLIENT(STRING(":hax.irc.andrewyu.org 003 me :This server was created 02:51:36 Apr 03 2023"));
+ SENDCLIENT(STRING(":hax.irc.andrewyu.org 004 me irc.andrewyu.org InspIRCd-3 BDGHILNORSTWcdghikorswxz ABCDEFGHIJKLMNOPQRSTXYZabcdefghijklmnopqrstuvwz :BEFHIJLXYZabdefghjkloqvw"));
+ SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me ACCEPT=100 AWAYLEN=200 BOT=B CALLERID=g CASEMAPPING=ascii CHANLIMIT=#:20 CHANMODES=IXZbegw,k,BEFHJLdfjl,ACDGKMNOPQRSTcimnprstuz CHANNELLEN=60 CHANTYPES=# ELIST=CMNTU ESILENCE=CcdiNnPpTtx EXCEPTS=e :are supported by this server"));
+ SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me EXTBAN=,ACNOQRSTUacjmnprswz HOSTLEN=64 INVEX=I KEYLEN=32 KICKLEN=300 LINELEN=512 MAXLIST=I:1000,X:1000,b:1000,e:1000,g:1000,w:1000 MAXTARGETS=20 MODES=20 MONITOR=30 NAMELEN=130 NAMESX NETWORK=LibreIRC :are supported by this server"));
+ SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me NICKLEN=30 OVERRIDE=O PREFIX=(Yqaohv)!~&@%+ REMOVE SAFELIST SECURELIST=60 SILENCE=100 STATUSMSG=!~&@%+ TOPICLEN=330 UHNAMES USERIP USERLEN=10 USERMODES=,,s,BDGHILNORSTWcdghikorwxz :are supported by this server"));
+ SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me WATCH=32 WHOX :are supported by this server"));
+
+ client_connected = 1;
+
+ return 0;
+}
+
+int client_join_handler(uint64_t argc, struct string *argv) {
+ if (argc < 1)
+ return 1;
+
+ SEND(STRING(":1HC FJOIN "));
+ SEND(argv[0]);
+ SEND(STRING(" "));
+ char current_time[22];
+ snprintf(current_time, 22, "%ld", time(NULL));
+ SEND(((struct string){current_time, strlen(current_time)}));
+ SEND(STRING(" + :,1HC000001\n"));
+
+ return 0;
+}
+
+int client_fd = -1;
+
+int client_listen_fd;
+int initclientnetwork(void) {
+ client_network_commands.array = malloc(0);
+
+ set_table_index(&client_network_commands, STRING("NICK"), &client_nick_handler);
+ set_table_index(&client_network_commands, STRING("USER"), &client_user_handler);
+ set_table_index(&client_network_commands, STRING("JOIN"), &client_join_handler);
+
+ client_nick.data = malloc(0);
+
+ client_listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (client_listen_fd < 0)
+ return 1;
+
+ struct sockaddr_in localhost = {
+ .sin_family = AF_INET,
+ .sin_port = htons(6667),
+ };
+ inet_pton(AF_INET, "127.0.0.1", &localhost.sin_addr); // this is indeed localhost for mine, and I have no intent to change this
+ bind(client_listen_fd, (struct sockaddr*)&localhost, sizeof(localhost));
+
+ listen(client_listen_fd, 1);
+
+ return 0;
+}
diff --git a/config.h b/config.h
index d343ed4..856e064 100644
--- a/config.h
+++ b/config.h
@@ -43,3 +43,5 @@ extern struct string prejoin_channels[];
extern uint64_t num_prejoin_channels;
extern struct string command_prefix;
+
+extern struct string client_hostmask;
diff --git a/main.c b/main.c
index e95d750..76b22e6 100644
--- a/main.c
+++ b/main.c
@@ -30,6 +30,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <pthread.h>
#include "network.h"
#include "config.h"
@@ -37,12 +38,181 @@
#include "tls.h"
#include "types.h"
+void *client_loop(void *ign) {
+ while (1) {
+ struct string full_msg = {.data = malloc(0), .len = 0};
+ WRITES(1, STRING("Yay\n"));
+ client_fd = accept(client_listen_fd, NULL, NULL);
+ listen(client_listen_fd, 0);
+ client_connected = 0;
+ client_nick.data = malloc(0);
+ while (1) {
+ char data[512];
+ uint64_t new_len = read(client_fd, data, 512);
+
+ if (new_len == 0) {
+ goto disconnect_client;
+ }
+
+ uint8_t found = 0;
+ uint64_t msg_len;
+ for (uint64_t i = 0; i < new_len; i++) {
+ if (data[i] == '\n') {
+ found = 1;
+ msg_len = i + full_msg.len;
+ break;
+ }
+ }
+
+ void *tmp = realloc(full_msg.data, full_msg.len+new_len);
+ if (tmp == 0 && full_msg.len+new_len != 0) {
+ WRITES(2, STRING("OOM... disconnect client.\n"));
+ goto disconnect_client;
+ }
+ full_msg.data = tmp;
+
+ memcpy(full_msg.data+full_msg.len, data, new_len);
+
+ full_msg.len += new_len;
+
+ if (!found)
+ continue;
+
+ while (1) {
+ WRITES(1, STRING("Recvd: "));
+ write(1, full_msg.data, msg_len+1); // +1: \n
+ if (full_msg.data[msg_len - 1] == '\r')
+ msg_len--;
+
+ uint64_t offset = 0;
+ while (offset < msg_len && full_msg.data[offset] == ' ')
+ offset++;
+
+ if (offset == msg_len) {
+ puts("Protocol violation: No command.");
+ goto disconnect_client;
+ }
+
+ struct string command;
+ command.data = full_msg.data+offset;
+ found = 0;
+ for (uint64_t i = offset; i < msg_len; i++) {
+ if (full_msg.data[i] == ' ') {
+ found = 1;
+ command.len = i - offset;
+ offset = i;
+ break;
+ }
+ }
+ if (!found) {
+ command.len = msg_len - offset;
+ offset = msg_len;
+ }
+
+ while (offset < msg_len && full_msg.data[offset] == ' ')
+ offset++;
+
+ uint64_t argc = 0;
+ uint64_t old_offset = offset;
+ if (offset < msg_len) {
+ while (offset < msg_len) {
+ if (full_msg.data[offset] == ':') {
+ argc++;
+ break;
+ }
+
+ while (offset < msg_len && full_msg.data[offset] != ' ')
+ offset++;
+
+ argc++;
+
+ while (offset < msg_len && full_msg.data[offset] == ' ')
+ offset++;
+ }
+ }
+ offset = old_offset;
+
+ struct string argv[argc];
+ if (offset < msg_len) {
+ uint64_t i = 0;
+ while (offset < msg_len) {
+ if (full_msg.data[offset] == ':') {
+ argv[i].data = full_msg.data+offset+1;
+ argv[i].len = msg_len - offset - 1;
+ break;
+ }
+
+ argv[i].data = full_msg.data+offset;
+ uint64_t start = offset;
+
+ while (offset < msg_len && full_msg.data[offset] != ' ')
+ offset++;
+
+ argv[i].len = offset - start;
+
+ while (offset < msg_len && full_msg.data[offset] == ' ')
+ offset++;
+
+ i++;
+ }
+ }
+
+ int (*func)(uint64_t argc, struct string *argv) = get_table_index(client_network_commands, command);
+
+ if (func == 0) {
+ WRITES(2, STRING("WARNING: Command is unknown, ignoring...\n"));
+ } else {
+ int err = func(argc, argv);
+ if (err) {
+ WRITES(1, STRING("Disconnecting client by result of the network command handler...\n"));
+ goto disconnect_client;
+ }
+ }
+ write(1, "\n", 1);
+
+ if (full_msg.data[msg_len] == '\r')
+ msg_len++;
+ memmove(full_msg.data, full_msg.data+msg_len+1, full_msg.len - msg_len - 1);
+ full_msg.len -= msg_len+1;
+
+ found = 0;
+ for (uint64_t i = 0; i < full_msg.len; i++) {
+ if (full_msg.data[i] == '\n') {
+ found = 1;
+ msg_len = i;
+ break;
+ }
+ }
+
+ if (found == 0) {
+ void *tmp = realloc(full_msg.data, full_msg.len);
+ if (tmp == 0 && full_msg.len != 0) {
+ puts("AAAAAAAAA (OOM shrinking allocated data?)");
+ goto disconnect_client;
+ }
+ full_msg.data = tmp;
+
+ break;
+ }
+ }
+ }
+ disconnect_client:
+ close(client_fd);
+ free(full_msg.data);
+ listen(client_listen_fd, 1);
+ }
+}
+
+pthread_t client_thread_id;
int main(void) {
initservernetwork();
+ initclientnetwork();
+
+ pthread_create(&client_thread_id, NULL, client_loop, NULL);
struct string full_msg = {malloc(0), 0};
while (1) {
- uint8_t data[512];
+ char data[512];
uint64_t new_len;
{
int len;
@@ -190,7 +360,7 @@ int main(void) {
}
}
- int (*func)(struct string source, uint64_t argc, struct string *argv) = get_table_index(network_commands, command);
+ int (*func)(struct string source, uint64_t argc, struct string *argv) = get_table_index(server_network_commands, command);
if (func == 0) {
WRITES(2, STRING("WARNING: Command is unknown, ignoring...\n"));
diff --git a/network.h b/network.h
index ac872d6..ced1d4d 100644
--- a/network.h
+++ b/network.h
@@ -59,9 +59,19 @@ struct user_info {
struct table metadata;
};
-extern struct table network_commands;
+extern struct table server_network_commands;
+extern struct table client_network_commands;
extern struct table server_list;
extern struct table user_list;
-int resolve(char* address, char* port, struct sockaddr *server);
-int initservernetwork(void);
+extern int client_fd;
+extern int client_listen_fd;
+extern struct string client_nick;
+extern uint8_t client_connected;
+
+extern int resolve(char* address, char* port, struct sockaddr *server);
+
+extern int initservernetwork(void);
+extern int initclientnetwork(void);
+
+#define SENDCLIENT(x) write(client_fd, x.data, x.len)
diff --git a/network.c b/server_network.c
index 70c58fe..0d7beb4 100644
--- a/network.c
+++ b/server_network.c
@@ -1,4 +1,4 @@
-// Network command handlers for HaxServ
+// Server network command handlers for HaxServ
//
// Written by: Test_User <hax@andrewyu.org>
//
@@ -28,11 +28,11 @@
#include <gnutls/gnutls.h>
#include <netdb.h>
-#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
+#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -63,7 +63,7 @@ int resolve(char *address, char *port, struct sockaddr *sockaddr) {
return success;
}
-struct table network_commands = {0};
+struct table server_network_commands = {0};
struct table server_list = {0};
struct table user_list = {0};
@@ -90,10 +90,7 @@ int ping_handler(struct string sender, uint64_t argc, struct string *argv) {
offset += sender.len;
msg[offset] = '\n';
- struct string m;
- m.data = msg;
- m.len = len;
- SEND(m);
+ SEND(((struct string){msg, len}));
return 0;
}
@@ -577,18 +574,18 @@ int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) {
}
int initservernetwork(void) {
- network_commands.array = malloc(0);
+ server_network_commands.array = malloc(0);
server_list.array = malloc(0);
user_list.array = malloc(0);
- set_table_index(&network_commands, STRING("PING"), &ping_handler);
- set_table_index(&network_commands, STRING("SERVER"), &server_handler);
- set_table_index(&network_commands, STRING("UID"), &uid_handler);
- set_table_index(&network_commands, STRING("OPERTYPE"), &opertype_handler);
- set_table_index(&network_commands, STRING("PRIVMSG"), &privmsg_handler);
- set_table_index(&network_commands, STRING("QUIT"), &quit_handler);
- set_table_index(&network_commands, STRING("KILL"), &kill_handler);
- set_table_index(&network_commands, STRING("NICK"), &nick_handler);
+ set_table_index(&server_network_commands, STRING("PING"), &ping_handler);
+ set_table_index(&server_network_commands, STRING("SERVER"), &server_handler);
+ set_table_index(&server_network_commands, STRING("UID"), &uid_handler);
+ set_table_index(&server_network_commands, STRING("OPERTYPE"), &opertype_handler);
+ set_table_index(&server_network_commands, STRING("PRIVMSG"), &privmsg_handler);
+ set_table_index(&server_network_commands, STRING("QUIT"), &quit_handler);
+ set_table_index(&server_network_commands, STRING("KILL"), &kill_handler);
+ set_table_index(&server_network_commands, STRING("NICK"), &nick_handler);
init_user_commands();
@@ -625,7 +622,7 @@ int initservernetwork(void) {
SEND(((struct string){current_time, strlen(current_time)}));
SEND(STRING(" + :,1HC000000\nMODE "));
SEND(prejoin_channels[i]);
- SEND(STRING(" +o 1HC000000\n"));
+ SEND(STRING(" +k 1HC000000\n:1HC000000 OPERTYPE Admin\n"));
}
SEND(STRING("ENDBURST\n"));