#include #include #include #include #include #include #include #include #include #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->irc_socket = socket(AF_INET, SOCK_STREAM, 0); if (irc->irc_socket < 0) return IRCC_ERROR; struct timeval tv = {IRCC_PING_TIMEOUT, 0}; if (setsockopt(irc->irc_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) return IRCC_ERROR; int status = connect(irc->irc_socket, (struct sockaddr *)&client_str, sizeof(client_str)); if (status == -1) return IRCC_ERROR; return IRCC_SUCCESS; } void IRCC_parse_msg(char *tmp, IRCC_client *irc) { irc->irc_raw[strcspn(irc->irc_raw, "\r\n")] = '\0'; if (tmp != NULL) { //Message char *val = strchr(tmp, ':'); if (val != NULL) { val[0] = '\0'; irc->irc_msg = val + 1; //Del space before : *(val - 1) = '\0'; } //Channel val = strchr(tmp, ' '); if (val != NULL) { val[0] = '\0'; irc->irc_channel = val + 1; } //Nickname val = strchr(irc->irc_raw, '!'); if (val != NULL) { val[0] = '\0'; irc->irc_nick = irc->irc_raw + 1; } } } int IRCC_recv(IRCC_client *irc) { memset(irc->irc_raw, '\0', IRCC_MSG_MAX); irc->irc_channel = NULL; irc->irc_msg = NULL; irc->irc_nick = NULL; int msg_size = recv(irc->irc_socket, irc->irc_raw, sizeof(irc->irc_raw), 0); if (msg_size == 0 || msg_size == -1) return IRCC_DISCONNECTED; else if (!strncmp(irc->irc_raw, "PING", 4)) { *(strchr(irc->irc_raw, 'I')) = 'O'; if (send(irc->irc_socket, irc->irc_raw, strlen(irc->irc_raw), 0) == -1) return IRCC_ERROR; return IRCC_PING; } return IRCC_SUCCESS; } int IRCC_parse(IRCC_client *irc) { //Check end of motd if (strstr(irc->irc_raw, "PRIVMSG ") == NULL && strstr(irc->irc_raw, "MOTD")) return IRCC_CONNECTED; //Other else if (strstr(irc->irc_raw, "PRIVMSG ")) { IRCC_parse_msg(strstr(irc->irc_raw, "PRIVMSG "), irc); return IRCC_PRIVMSG; } else if (strstr(irc->irc_raw, "NICK ")) { IRCC_parse_msg(strstr(irc->irc_raw, "NICK "), irc); return IRCC_NICK; } else if (strstr(irc->irc_raw, "TOPIC ")) { IRCC_parse_msg(strstr(irc->irc_raw, "TOPIC "), irc); return IRCC_TOPIC; } else if (strstr(irc->irc_raw, "MODE ")) { IRCC_parse_msg(strstr(irc->irc_raw, "MODE "), irc); return IRCC_MODE; } else if (strstr(irc->irc_raw, "JOIN ")) { IRCC_parse_msg(strstr(irc->irc_raw, "JOIN "), irc); return IRCC_JOIN; } else if (strstr(irc->irc_raw, "PART ") || strstr(irc->irc_raw, "QUIT ")) { IRCC_parse_msg(strstr(irc->irc_raw, "PART "), irc); IRCC_parse_msg(strstr(irc->irc_raw, "QUIT "), irc); return IRCC_PART; } return IRCC_SUCCESS; } int IRCC_register(IRCC_client *irc, const char *nickname) { off_t bytes = snprintf(irc->irc_raw, sizeof(irc->irc_raw), "NICK %s\r\n", nickname); if (send(irc->irc_socket, irc->irc_raw, bytes, 0) == -1) return IRCC_ERROR; bytes = snprintf(irc->irc_raw, sizeof(irc->irc_raw), "USER %s 0 localhost :%s\r\n", nickname, nickname); if (send(irc->irc_socket, irc->irc_raw, bytes, 0) == -1) return IRCC_ERROR; //Motd skip while (1) { int status = IRCC_recv(irc); if (status == IRCC_DISCONNECTED) return IRCC_DISCONNECTED; status = IRCC_parse(irc); if (status == IRCC_CONNECTED) break; } return IRCC_SUCCESS; } int IRCC_join(IRCC_client *irc, const char *channel, const char *key) { off_t bytes = snprintf(irc->irc_raw, sizeof(irc->irc_raw), "JOIN %s %s\r\n", channel, (key) ? key : ""); if (send(irc->irc_socket, irc->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->irc_raw, sizeof(irc->irc_raw), "PRIVMSG %s :%s\r\n", channel, msg); if (send(irc->irc_socket, irc->irc_raw, bytes, 0) == -1) return IRCC_ERROR; return IRCC_SUCCESS; } void IRCC_init(IRCC_client *irc) { irc->irc_msg = irc->irc_nick = irc->irc_channel = NULL; } void IRCC_close(IRCC_client *irc) { close(irc->irc_socket); irc->irc_msg = irc->irc_nick = irc->irc_channel = NULL; }