#include "irc.h" int IRCC_connect(IRCC_client *irc, const char *ip, const unsigned int port){ struct hostent *hp = gethostbyname(ip); if (!hp) return IRCC_ERROR; //Only ipv4 struct sockaddr_in client_str; memset(&client_str, 0, sizeof(client_str)); client_str.sin_family = AF_INET; client_str.sin_port = htons(port); client_str.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)hp->h_addr)); irc->socket = socket(AF_INET, SOCK_STREAM, 0); if (irc->socket < 0) return IRCC_ERROR; struct timeval tv = {IRCC_PING_TIMEOUT, 0}; if (setsockopt(irc->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) return IRCC_ERROR; int status = connect(irc->socket, (struct sockaddr *)&client_str, sizeof(client_str)); if (status == -1) return IRCC_ERROR; return IRCC_SUCCESS; } void IRCC_parse(char *tmp, IRCC_client *irc){ irc->raw[strcspn(irc->raw, "\r\n")] = '\0'; if (tmp != NULL){ //Message char *val = strchr(tmp, ':'); if (val != NULL) { val[0] = '\0'; irc->msg = val + 1; //Del space before : *(val - 1) = '\0'; } //Channel val = strchr(tmp, ' '); if (val != NULL) { val[0] = '\0'; irc->channel = val + 1; } //Nickname val = strchr(irc->raw, '!'); if (val != NULL) { val[0] = '\0'; irc->nick = irc->raw + 1; } } } int IRCC_recv(IRCC_client *irc){ memset(irc->raw, '\0', IRCC_MSG_MAX); irc->channel = NULL; irc->msg = NULL; irc->nick = NULL; int msg_size = recv(irc->socket, irc->raw, sizeof(irc->raw), 0); if (msg_size == 0 || msg_size == -1) return IRCC_DISCONNECTED; else if (!strncmp(irc->raw, "PING", 4)){ *(strchr(irc->raw, 'I')) = 'O'; if (send(irc->socket, irc->raw, strlen(irc->raw), 0) == -1) return IRCC_ERROR; return IRCC_PING; } else { #ifdef IRCC_DEBUG puts(irc->raw); #endif //Check end of motd if (strstr(irc->raw, "PRIVMSG ") == NULL && strstr(irc->raw, "MOTD")) return IRCC_CONNECTED; //Other else if (strstr(irc->raw, "PRIVMSG ")){ IRCC_parse(strstr(irc->raw, "PRIVMSG "), irc); return IRCC_PRIVMSG; } else if (strstr(irc->raw, "NICK ")){ IRCC_parse(strstr(irc->raw, "NICK "), irc); return IRCC_NICK; } else if (strstr(irc->raw, "TOPIC ")){ IRCC_parse(strstr(irc->raw, "TOPIC "), irc); return IRCC_TOPIC; } else if (strstr(irc->raw, "MODE ")){ IRCC_parse(strstr(irc->raw, "MODE "), irc); return IRCC_MODE; } else if (strstr(irc->raw, "JOIN ")){ IRCC_parse(strstr(irc->raw, "JOIN "), irc); return IRCC_JOIN; } else if (strstr(irc->raw, "PART ") || strstr(irc->raw, "QUIT ")){ IRCC_parse(strstr(irc->raw, "PART "), irc); IRCC_parse(strstr(irc->raw, "QUIT "), irc); return IRCC_PART; } } return IRCC_SUCCESS; } int IRCC_register(IRCC_client *irc, const char *nickname){ off_t bytes = snprintf(irc->raw, sizeof(irc->raw), "NICK %s\r\n", nickname); if (send(irc->socket, irc->raw, bytes, 0) == -1) return IRCC_ERROR; bytes = snprintf(irc->raw, sizeof(irc->raw), "USER %s 0 localhost :%s\r\n", nickname, nickname); if (send(irc->socket, irc->raw, bytes, 0) == -1) return IRCC_ERROR; //Motd skip while (1) { int status = IRCC_recv(irc); if (status == IRCC_CONNECTED) break; else if (status == IRCC_DISCONNECTED) return IRCC_DISCONNECTED; } return IRCC_SUCCESS; } int IRCC_join(IRCC_client *irc, const char *channel, const char *key){ off_t bytes = snprintf(irc->raw, sizeof(irc->raw), "JOIN %s %s\r\n", channel, (key) ? key : ""); if (send(irc->socket, irc->raw, bytes, 0) == -1) return IRCC_ERROR; return IRCC_SUCCESS; } int IRCC_send(IRCC_client *irc, const char *channel, const char *msg){ off_t bytes = snprintf(irc->raw, sizeof(irc->raw), "PRIVMSG %s :%s\r\n", channel, msg); if (send(irc->socket, irc->raw, bytes, 0) == -1) return IRCC_ERROR; return IRCC_SUCCESS; } int IRCC_init(IRCC_client *irc) { irc->msg = irc->nick = irc->channel = NULL; return IRCC_SUCCESS; } void IRCC_close(IRCC_client *irc){ close(irc->socket); irc->msg = irc->nick = irc->channel = NULL; }