From 1e73bdc8b81a37a8b674f4d1596e29d0b0a50902 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Thu, 13 Jan 2022 02:54:34 +0000 Subject: fix irc handling code and also add makefile --- thing.c | 382 ++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 215 insertions(+), 167 deletions(-) (limited to 'thing.c') 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 #include #include +#include #include #include #include #include #include #include +#include #include #include #include -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; } -- cgit v1.2.3