aboutsummaryrefslogtreecommitdiff
path: root/thing.c
diff options
context:
space:
mode:
Diffstat (limited to 'thing.c')
-rw-r--r--thing.c382
1 files changed, 215 insertions, 167 deletions
diff --git a/thing.c b/thing.c
index 2ffd843..9cd85f9 100644
--- a/thing.c
+++ b/thing.c
@@ -1,210 +1,258 @@
#ifdef LOCAL
#define HOST "0.0.0.0"
-#define PORT "6970"
+#define PORT "6971"
#else
#define HOST "ubq323.website"
#define PORT "6667"
#endif
+#ifdef DEBUG
+#define DP(x) puts(x)
+#else
+#define DP(x)
+#endif
+
#define NICK "ffbm"
#define USERNAME "ffbm"
#define REALNAME ",flappy fly bird man?"
#define CHANNEL "#a"
-#define PIPE "/run/apionet.pipe"
-
-#define _GNU_SOURCE
+#define SOCKETNAME "bees.sock"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
-int hasjoined = 0;
-
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);
- total_sent = 0;
- do {
- if ((sent = write(0, buf+total_sent, len-total_sent)) == -1) {
- return -1;
- }
- total_sent += sent;
- } while (total_sent < len);
- return total_sent;
+ 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);
+
+ char *the = strndup(buf, len);
+ printf("SEND [%s]\n",the);
+ free(the);
+
+ return total_sent;
}
int irc_connect() {
- struct addrinfo hints;
- int status, sockfd;
- struct addrinfo *res;
-
- memset(&hints, 0, sizeof hints);
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-
- // assuming the first one is valid because it normally is
-
- if ((status = getaddrinfo(HOST, PORT, &hints, &res)) != 0) {
- fprintf(stderr, "getaddrinfo fail: %s\n", gai_strerror(status));
- return -1;
- }
-
- if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
- perror("socket");
- return -1;
- }
- if (connect(sockfd, res->ai_addr, res->ai_addrlen) != 0) {
- perror("connect");
- return -1;
- }
- return sockfd;
+ struct addrinfo hints;
+ int status, sockfd;
+ struct addrinfo *res;
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ // assuming the first one is valid because it normally is
+
+ if ((status = getaddrinfo(HOST, PORT, &hints, &res)) != 0) {
+ fprintf(stderr, "getaddrinfo fail: %s\n", gai_strerror(status));
+ return -1;
+ }
+
+ if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
+ perror("socket");
+ return -1;
+ }
+ if (connect(sockfd, res->ai_addr, res->ai_addrlen) != 0) {
+ perror("connect");
+ return -1;
+ }
+ return sockfd;
}
int irc_handshake(int sockfd) {
- char msg[] = "NICK "NICK"\r\nUSER "USERNAME" 0 * :"REALNAME"\r\nJOIN "CHANNEL"\r\n";
- if (sendall(sockfd, msg, sizeof msg-1) == -1) {
- return -1;
- }
- return 0;
+ char msg[] = "NICK "NICK"\r\nUSER "USERNAME" 0 * :"REALNAME"\r\nJOIN "CHANNEL"\r\n";
+ if (sendall(sockfd, msg, sizeof msg-1) == -1) {
+ return -1;
+ }
+ return 0;
}
void irc_handle(int sockfd, char *start, char *end) {
- if (strncmp(start, "PING", 4) == 0) {
- start[1] = 'O';
- sendall(sockfd, start, end-start);
- start[1] = 'I';
- }
- char *str = strndup(start, end-start);
- printf("[%s]\n",str);
- free(str);
+ DP("irc_handle...");
+ char *the = strndup(start,end-start);
+ printf("HANDLE [%s]\n",the);
+ free(the);
+
+ if (strncmp(start, "PING", 4) == 0) {
+ start[1] = 'O';
+ sendall(sockfd, start, end-start);
+ start[1] = 'I';
+ }
+
+
+
+
}
+#define IRC_RECVBUF_SIZE 1024
+char irc_recvbuf[IRC_RECVBUF_SIZE];
+const char *irc_recvbuf_end = &irc_recvbuf[IRC_RECVBUF_SIZE];
+char *irc_recvbuf_cur = &irc_recvbuf[0];
+
void irc_recv(int sockfd) {
- char recvbuf[1024];
- ssize_t amt;
- if ((amt = recv(sockfd, recvbuf, 1024, 0)) == -1) {
- perror("recv");
- exit(1);
- }
-
- char *start = &recvbuf[0];
- char *cur;
- char *end = start+amt ;
- for (cur = start; cur < end; cur++) {
- if (*cur == '\r' && *(cur+1) == '\n') {
- irc_handle(sockfd, start, cur+2);
- start = cur + 2;
- cur = start;
- }
- }
+ DP("irc_recv...");
+
+
+ ssize_t s = recv(sockfd, irc_recvbuf_cur, irc_recvbuf_end-irc_recvbuf_cur, 0);
+
+ if (s == 0) {
+ fputs("socket eof\n",stderr);
+ exit(3); // todo: reconnecting properly
+ }
+
+ if (s == -1) {
+ perror("recv");
+ exit(1);
+ }
+
+ char *the = strndup(irc_recvbuf_cur,s);
+ printf("RECV %ld [%s]\n",s,the);
+ free(the);
+
+ char *buf_last = irc_recvbuf_cur+s;
+
+ char *cur;
+ char *start = irc_recvbuf;
+ for (cur = irc_recvbuf; cur < buf_last; cur++) {
+ if (*cur=='\r' && *(cur+1) == '\n') {
+ irc_handle(sockfd, start, cur+2);
+ start = cur+2;
+ cur++;
+ }
+ }
+
+ if (start == buf_last) {
+ // all done
+ irc_recvbuf_cur = irc_recvbuf;
+ } else {
+ size_t remainder_len = buf_last-start;
+ // if we are to support ircv3 message tags then this should be
+ // quite a lot bigger, but i don't care about that
+ // (buffer would have to be bigger too, at least 16384 i think)
+ if (remainder_len > 512) {
+ fputs("message longer than 512 bytes! this indicates a broken server\n",stderr);
+ exit(2);
+ }
+ memmove(irc_recvbuf,start,remainder_len);
+ irc_recvbuf_cur = irc_recvbuf+remainder_len;
+ }
}
+
+
+
+int unix_setup() {
+ unlink(SOCKETNAME);
+
+ int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ perror("(unix) socket");
+ return -1;
+ }
+
+ struct sockaddr_un name;
+ memset(&name, 0, sizeof name);
+ name.sun_family = AF_UNIX;
+ strncpy(name.sun_path, SOCKETNAME, (sizeof name.sun_path)-1);
+ if (bind(sock, (const struct sockaddr*)&name, sizeof name) == -1) {
+ perror("(unix) bind");
+ return -1;
+ }
+ return sock;
+}
+
+
int main(int argc, char *argv[]) {
- // this only works on linux, i think.
- // sorry
- int pipefd = open(PIPE, O_RDWR|O_NONBLOCK);
- if (pipefd == -1) {
- perror("(pipe) open");
- return 1;
- }
-
- printf("bees\n");
- int sockfd = irc_connect();
- if (sockfd == -1) {
- return 1;
- }
- if (irc_handshake(sockfd) != 0) {
- perror("irc_handshake");
- return 1;
- }
-
- // setup pollfds
- struct pollfd pollfds[2] = {
- {
- .fd = pipefd,
- .events = POLLIN,
- },
- {
- .fd = sockfd,
- .events = POLLIN,
- },
- };
- printf("POLLIN %d POLLERR %d POLLHUP %d\n",POLLIN,POLLERR,POLLHUP);
- for (;;) {
- int r;
- if ((r = poll(pollfds, 2, -1)) == -1) {
- perror("poll");
- return 1;
- }
- printf("poll %d\n",r);
- printf("sock %d pipe %d\n",pollfds[1].revents, pollfds[0].revents);
-
- if (pollfds[1].revents & POLLHUP) {
- // socket closed, probably
- puts("socket hup");
- break;
- }
- if (pollfds[1].revents & POLLERR) {
- // socket error
- puts("socket err");
- break;
- }
- if (pollfds[1].revents & POLLIN) {
- // socket
- char buf[1];
- // there is probably a better way of doing this
- // but if there is, i don't know what it is
- ssize_t h = recv(sockfd, buf, 1, MSG_PEEK);
- if (h<0) {
- perror("recv");
- return -1;
- } else if (h == 0) {
- // eof ish
- puts("socket end");
- break;
- } else {
- irc_recv(sockfd);
- }
- }
- if (pollfds[0].revents & POLLIN) {
- puts("pipe");
- ssize_t amt;
- unsigned char buf[128];
- if ((amt = read(pipefd, buf, 128)) == -1) {
- perror("(pipe) read");
- return 1;
- }
- for (size_t i = 0; i < amt; i++) {
- if (buf[i] == '\r' || buf[i] == '\n' || buf[i] < ' ') {
- buf[i] = ' ';
- }
- }
- char msg[] = "PRIVMSG "CHANNEL" :";
-
- if (sendall(sockfd, msg, sizeof msg-1) == -1) { perror("sendall"); exit(1); }
- if (sendall(sockfd, buf, amt) == -1) { perror("sendall"); exit(1); }
- if (sendall(sockfd, "\r\n", 2) == -1) { perror("sendall"); exit(1); }
- }
- }
-
-
-
-
- return 0;
+
+ int ircsock = irc_connect();
+ if (ircsock == -1) {
+ return 1;
+ }
+ if (irc_handshake(ircsock) != 0) {
+ perror("irc_handshake");
+ return 1;
+ }
+
+ int unixsock = unix_setup();
+ if (unixsock == -1)
+ return 1;
+
+ struct pollfd pollfds[2] = {
+ {
+ .fd = unixsock,
+ .events = POLLIN,
+ },
+ {
+ .fd = ircsock,
+ .events = POLLIN,
+ },
+ };
+ printf("POLLIN %d POLLERR %d POLLHUP %d\n",POLLIN,POLLERR,POLLHUP);
+
+ for (;;) {
+ int r;
+ if ((r = poll(pollfds, 2, -1)) == -1) {
+ perror("poll");
+ return 1;
+ }
+ printf("sock %d unix %d\n",pollfds[1].revents, pollfds[0].revents);
+
+
+ if (pollfds[1].revents & POLLHUP) {
+ // socket closed, probably
+ puts("socket hup");
+ break;
+ }
+ if (pollfds[1].revents & POLLERR) {
+ // socket error
+ puts("socket err");
+ break;
+ }
+ if (pollfds[1].revents & POLLIN) {
+ DP("socket...");
+ // socket
+ irc_recv(ircsock);
+ }
+ if (pollfds[0].revents & POLLIN) {
+ unsigned char buf[128];
+ ssize_t amt;
+ if ((amt = recv(unixsock,buf,sizeof buf,0)) == -1) {
+ perror("(unix) read");
+ return 1;
+ }
+ for (size_t i = 0; i < amt; i++)
+ if (buf[i] == '\r' || buf[i] == '\n' || buf[i] < ' ')
+ buf[i] = ' ';
+ char msg[] = "PRIVMSG "CHANNEL" :";
+
+ if (sendall(ircsock, msg, sizeof msg-1) == -1) { perror("sendall"); return 1; }
+ if (sendall(ircsock, buf, amt) == -1) { perror("sendall"); return 1; }
+ if (sendall(ircsock, "\r\n", 2) == -1) { perror("sendall"); return 1; }
+
+ }
+ }
+
+
+
+
+ return 0;
}