From 7a17c3a4ea869a04041ff2568fd02ec676ab8dff Mon Sep 17 00:00:00 2001
From: ubq323 <ubq323@ubq323.website>
Date: Fri, 28 Oct 2022 00:48:14 +0100
Subject: large refactor continues

---
 Makefile |  22 +++++++----
 bee.c    |  19 ++++++++++
 common.c |  31 +++++++++++++++
 conf.h   |  40 ++++++++++++++++++++
 irc.c    | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 irc.h    |  29 ++++++++++++++
 thing.c  |  39 +------------------
 util.c   |  17 +++++++++
 util.h   |  16 ++++++++
 9 files changed, 297 insertions(+), 46 deletions(-)
 create mode 100644 bee.c
 create mode 100644 common.c
 create mode 100644 conf.h
 create mode 100644 irc.c
 create mode 100644 irc.h
 create mode 100644 util.c
 create mode 100644 util.h

diff --git a/Makefile b/Makefile
index df7073c..cb02b50 100644
--- a/Makefile
+++ b/Makefile
@@ -1,21 +1,27 @@
 .POSIX:
-.SUFFIXES:
+.SUFFIXES: .c .o
 
 CFLAGS=-Wall
 CC=cc
 debug=-g -DDEBUG -DLOCAL
-fs=thing.c
 
-all: thing
+OBJS=bee.o irc.o util.o
 
-thing: $(fs)
-	$(CC) $(CFLAGS) -o thing $(fs)
+all: apiobot
+apiobot: $(OBJS)
+	$(CC) $(CFLAGS) -o apiobot $(OBJS)
 
 debug:
-	$(CC) $(CFLAGS) $(debug) -o thing $(fs)
+	$(CC) $(CFLAGS) $(debug) -o apiobot $(OBJS)
+
+.c.o:
+	$(CC) -c $< $(CFLAGS) -o $@
 
 run: all
-	./thing
+	./apiobot
 
 dr: debug
-	./thing
+	./apiobot
+
+clean:
+	rm *.o apiobot
diff --git a/bee.c b/bee.c
new file mode 100644
index 0000000..f7d1270
--- /dev/null
+++ b/bee.c
@@ -0,0 +1,19 @@
+#include "irc.h"
+
+#include <stdio.h>
+
+
+int
+main()
+{
+	if (!irc_connect()) { fputs("irc_connect\n",stderr); return 1; }
+	if (!irc_handshake()) { fputs("irc_handshake\n",stderr); return 1; }
+
+	int x;
+	do {
+		x = irc_recv();
+	} while (!x);
+
+	return 0;
+}
+
diff --git a/common.c b/common.c
new file mode 100644
index 0000000..f217001
--- /dev/null
+++ b/common.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <string.h>
+
+
+#define SOCKDIR "/run/apionet"
+
+int
+channel_socket_path(char chname[], char out[], size_t lim)
+{
+	if (strlen(chname) > 16) return -1;
+	if (snprintf(out, lim, SOCKDIR "/apionet.%s.sock", chname) >= lim)
+		return -1;
+	return 0;
+}
+
+char *channels[] = {
+	"a","b","robots","jonathan","secret-channel",NULL,
+};
+
+int
+main()
+{
+	char b[200];
+	for (int i = 0; channels[i]; i++) {
+		memset(b,0,200);
+		channel_socket_path(channels[i], b, 200);
+		printf("%s\n",b);
+	}
+	return 0;
+}
+	
diff --git a/conf.h b/conf.h
new file mode 100644
index 0000000..80d7181
--- /dev/null
+++ b/conf.h
@@ -0,0 +1,40 @@
+#ifndef conf_h_INCLUDED
+#define conf_h_INCLUDED
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef LOCAL
+	#define HOST "0.0.0.0"
+	#define PORT "6971"
+	#define SOCKETNAME "bees.sock"
+	#define SOCKETGROUP "cdrom"
+#else
+	#define HOST "ubq323.website"
+	#define PORT "6667"
+	#define SOCKETNAME "/srv/apiobot/bees.sock"
+	#define SOCKETGROUP "apionet"
+#endif
+
+#ifdef DEBUG
+	#define DP(x) puts(x)
+	#define DPn(name,x,len) \
+		do {    \
+			char *__xxx = strndup(x,len); \
+			printf(name " [%s]\n",__xxx); \
+			free(__xxx); \
+		} while (0)
+#else
+	#define DP(x)
+	#define DPn(n,x,l)
+#endif
+
+#define NICK "Bee"
+#define USERNAME "apiobot"
+#define REALNAME "apiobot"
+#define CHANNEL "#a"
+
+
+#endif // conf_h_INCLUDED
+
diff --git a/irc.c b/irc.c
new file mode 100644
index 0000000..5c206bd
--- /dev/null
+++ b/irc.c
@@ -0,0 +1,130 @@
+
+#include "irc.h"
+#include "conf.h"
+#include "util.h"
+
+int g_ircsock = -1;
+
+int
+irc_connect()
+{
+	struct addrinfo hints;
+	memset(&hints, 0, sizeof hints);
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+
+	int status;
+	struct addrinfo *res;
+	if ((status = getaddrinfo(HOST, PORT, &hints, &res)) != 0) {
+		fprintf(stderr, "gettaddrinfo fail: %s\n", gai_strerror(status));
+		return -1;
+	}
+
+	int sockfd;
+	for (; res != NULL; res = res->ai_next) {
+		if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
+			perror("socket");
+			continue;
+		}
+		if (connect(sockfd, res->ai_addr, res->ai_addrlen) != 0) {
+			perror("connect");
+			continue;
+		}
+		goto success;
+	}
+	return -1;
+success:
+	g_ircsock = sockfd;
+	return 0;
+}
+
+int 
+irc_sendall(char msg[], size_t len)
+{
+	return sendall(g_ircsock,  msg, len);
+}
+
+int
+irc_handshake()
+{
+	char msg[] = "NICK "NICK"\r\nUSER "USERNAME" 0 * :"REALNAME"\r\nJOIN "CHANNEL"\r\n";
+	return irc_sendall(msg, sizeof msg-1);
+}
+
+
+
+/* **** */
+
+static void
+handle(char msg[], size_t len)
+{
+	printf("HANDLE {");
+	int i;
+	for (i=0; i<len; i++) {
+		switch (msg[i]) {
+		case '\r':
+			printf("<CR>");
+			break;
+		case '\n':
+			printf("<LF>");
+			break;
+		default:
+			putchar(msg[i]);
+			break;
+		}
+	}
+	printf("}\n");
+}
+
+
+#define RECVBUF_SIZE 1024
+char recv_buf[RECVBUF_SIZE];
+char *recv_cur = &recv_buf[0];
+// one past the end
+char *recv_end = &recv_buf[RECVBUF_SIZE];
+
+// i can't be bothered to implement a proper circular buffer
+// (it'd be more effort than this anyway, for very little gain)
+// the start of the buffer (index 0) is always the start of the buffer
+// then cur points to one past the most recently recieved byte.
+// after processing a message, if there's more stuff in the buffer, memmove it back.
+
+int
+irc_recv()
+{
+	ssize_t amt;
+	if ((amt = recv(g_ircsock, recv_cur, recv_end-recv_cur, 0)) == -1) {
+		// socket error
+		perror("recv");
+		return -1;
+	} else if (amt == 0) {
+		// eof
+		fprintf(stderr,"irc eof\n");
+		return -1;
+	}
+
+	// find the end of a message
+	char *c;
+	char *end = recv_cur+amt;
+	char *msg_start = recv_buf;
+	for (c=recv_buf; c<end; c++) {
+		if (*c == '\r' && *(c+1) == '\n') {
+			handle(msg_start, (c+2)-msg_start);
+			msg_start = c+2;
+			c++;
+		}
+	}
+
+	if (msg_start == end) 
+		recv_cur = recv_buf;
+	else {
+		size_t remlen = end - msg_start;
+		if (remlen > 512) {
+			fprintf(stderr,"my receive buffer is filled with NONSENSE!!!\n");
+			return -1;
+		}
+		memmove(recv_buf, msg_start, remlen);
+	}
+
+	return 0;
+}
diff --git a/irc.h b/irc.h
new file mode 100644
index 0000000..a56379d
--- /dev/null
+++ b/irc.h
@@ -0,0 +1,29 @@
+#ifndef irc_h_INCLUDED
+#define irc_h_INCLUDED
+
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+
+#define IRC_RECVBUF_SIZE 1024
+
+extern int g_ircsock;
+
+// connects to the irc server, as defined in config.h
+// returns -1 on failure.
+int irc_connect();
+
+int irc_handshake();
+
+// reads from irc socket into its buffer.
+// if a full message / many full messages are available, handles them all.
+int irc_recv();
+
+// sends a string to the irc socket. returns -1 on failure.
+int irc_sendall(char msg[], size_t len);
+
+#endif // irc_h_INCLUDED
+
diff --git a/thing.c b/thing.c
index 6ea805a..3f84948 100644
--- a/thing.c
+++ b/thing.c
@@ -1,25 +1,4 @@
-#ifdef LOCAL
-#define HOST "0.0.0.0"
-#define PORT "6971"
-#define SOCKETNAME "bees.sock"
-#else
-#define HOST "ubq323.website"
-#define PORT "6667"
-#define SOCKETNAME "/srv/apiobot/bees.sock"
-#endif
-
-#ifdef DEBUG
-#define DP(x) puts(x)
-#else
-#define DP(x)
-#endif
-
-#define NICK "Bee"
-#define USERNAME "apiobot"
-#define REALNAME "apiobot"
-#define CHANNEL "#a"
-
-#define SOCKETGROUP "apionet"
+#include "conf.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,22 +16,6 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
-ssize_t sendall(int sockfd, void *buf, size_t len) {
-	ssize_t total_sent = 0;
-	ssize_t sent;
-	do {
-		if ((sent = send(sockfd, buf+total_sent, len-total_sent, 0)) == -1) {
-			return -1;
-		}
-		total_sent += sent;
-	} while (total_sent < len);
-#ifdef DEBUG
-	char *the = strndup(buf, len);
-	printf("SEND [%s]\n",the);
-	free(the);
-#endif
-	return total_sent;
-}
 
 int irc_connect() {
 	struct addrinfo hints;
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..c545724
--- /dev/null
+++ b/util.c
@@ -0,0 +1,17 @@
+#include "util.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+ssize_t sendall(int sockfd, void *buf, size_t len) {
+	ssize_t total_sent = 0;
+	ssize_t sent;
+	do {
+		if ((sent = send(sockfd, buf+total_sent, len-total_sent, 0)) == -1) {
+			return -1;
+		}
+		total_sent += sent;
+	} while (total_sent < len);
+	DPn("SEND",buf,len);
+	return total_sent;
+}
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..f273e2f
--- /dev/null
+++ b/util.h
@@ -0,0 +1,16 @@
+#ifndef util_h_INCLUDED
+#define util_h_INCLUDED
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stddef.h>
+#include "conf.h"
+
+// repeatedly call send until all the data has been sent down
+// the socket.
+ssize_t sendall(int sockfd, void *buf, size_t len);
+
+
+
+#endif // util_h_INCLUDED
+
-- 
cgit v1.2.3