#include "irc.h" #include "debug.h" #include "chanlist.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; printf("connecting to %s:%s....\n",HOST,PORT); 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() { #define E(x) do { if (x==-1) { perror("irc_sendall"); return -1; } } while(0) char msg1[] = "NICK "NICK"\r\nUSER "USERNAME" 0 * :"REALNAME"\r\n"; E(irc_sendall(msg1, sizeof msg1-1)); for (int i = 0; i 16) { fprintf(stderr,"channel name too long (%s)\n",g_chanlist[i]); return -1; } E(irc_sendall("JOIN #",6)); E(irc_sendall(g_chanlist[i],strlen(g_chanlist[i]))); if (g_chanpwlist[i] != NULL) { if (strlen(g_chanpwlist[i]) > 64) { fprintf(stderr,"channel password too long for #(%s)\n",g_chanlist[i]); return -1; } E(irc_sendall(" ",1)); E(irc_sendall(g_chanpwlist[i],strlen(g_chanpwlist[i]))); } E(irc_sendall("\r\n",2)); } #undef E return 0; } /* **** */ static void handle(char msg[], size_t len) { printf("HANDLE {"); int i; for (i=0; i"); break; case '\n': printf(""); break; default: putchar(msg[i]); break; } } printf("}\n"); if (len >=4 && strncmp(msg, "PING", 4) == 0) { DP("ponging"); // this modifies buffer in place. which is presumably fine msg[1] = 'O'; irc_sendall(msg,len); } } #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. // returns -2 on eof, -1 on other error, 0 on success 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 -2; } DPf("recieved %ld ",amt); // find the end of a message char *c; char *end = recv_cur+amt; char *msg_start = recv_buf; DPn("BUF",recv_buf,end-recv_buf); for (c=recv_buf; c 512) { fprintf(stderr,"my receive buffer is filled with NONSENSE!!!\n"); return -1; } if (recv_buf != msg_start) { DPf("mem moving %ld\n",remlen); memmove(recv_buf, msg_start, remlen); } recv_cur = recv_buf + remlen; } return 0; }