aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile22
-rw-r--r--bee.c19
-rw-r--r--common.c31
-rw-r--r--conf.h40
-rw-r--r--irc.c130
-rw-r--r--irc.h29
-rw-r--r--thing.c39
-rw-r--r--util.c17
-rw-r--r--util.h16
9 files changed, 297 insertions, 46 deletions
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
+