Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Contains the functions the bot uses to connect
- #include <string.h> //For String functions
- #include <stdio.h> //For standard input/output
- #include <errno.h> //For errors
- //Needed for getaddrinfo(), socket(), etc.
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include "netstructs.h" //Contains the data structures used for connections
- #include "connect.h"
- int irc_connect(struct irc_network * network) {
- struct addrinfo hints; //Hints for getaddrinfo()
- struct addrinfo * results; //Points to the results from getaddrinfo()
- //Clean the hints structure
- memset(&hints, '\0', sizeof(struct addrinfo));
- //Set up hints structure
- hints.ai_family = AF_UNSPEC; //Can be IPv4 or 6
- hints.ai_socktype = SOCK_DGRAM; //Datagram socket
- hints.ai_flags = 0;
- hints.ai_protocol = 0; //Any protocol
- //Attempt to connect using the information provided in network
- if (getaddrinfo(network->hostname, network->port, &hints, &results) != 0)
- return -1;
- //Loop through the list of address structures returned by getaddrinfo until we connect
- struct addrinfo * cur; //Points to the structure we're currently trying
- for (cur = results; cur != NULL; cur = cur->ai_next) {
- //Attempt to make socket
- network->__socket = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
- //If it fails, go back to the beggining and try with the next structure
- if (network->__socket == -1)
- continue;
- //If it doesn't, then attempt to connect, if that works then we're done here
- if (connect(network->__socket, cur->ai_addr, cur->ai_addrlen) != -1)
- break;
- //It didn't work, so we'll close the socket and go back to the beginning
- close(network->__socket);
- }
- //Check if we connected, if not return an error
- if (cur == NULL)
- return -1;
- //We don't need the results anymore, so free the allocated memory
- freeaddrinfo(results);
- //Send our nickname information to the server
- char msgbuf[512]; //512 is the standard maximum length of an IRC message
- snprintf(&msgbuf, 512, "NICK %s\r\n", network->nickname);
- send(network->__socket, &msgbuf, strlen(&msgbuf), 0);
- //Now send our user info to the server
- snprintf(&msgbuf, 512, "USER %s %s %s :%s\r\n",
- network->username, network->user_hostname, network->hostname, network->realname);
- send(network->__socket, &msgbuf, strlen(&msgbuf), 0);
- //Before we indicate we've finished, we want to make sure the network structure and cursor are initialized
- network->__read_cursor = &network->__read_buf[0]; //Set the cursor at the beggining of the buffer
- memset(&network->__read_buf, '\0', 513); //Clean the read buffer
- network->__read_buf[512] = '\0'; //Set the last character in the buffer to a null byte
- network->__data_waiting = false; //Indicate there's no data in the buffer yet
- //Information sent, if all went well we should be connected!
- return 0;
- }
- int __irc_read(struct irc_network * network, char * res) {
- //Check if there are still messages waiting to be parsed in __read_buf
- if (network->__data_waiting) {
- //Figure out how much space we have left in the buffer after the cursor
- size_t space_left = &network->__read_buf[511] - network->__read_cursor;
- //Find the end of the next message
- char * eom = strstr(network->__read_cursor, "\r\n"); //End Of Message
- if (eom == NULL) { //If only a partially completed message is found
- //Move the current message to the front of the buffer
- memmove(&network->__read_buf, network->__read_cursor, space_left);
- //Update the cursor, and recalculate space_left
- network->__read_cursor = &network->__read_buf[space_left];
- space_left = &network->__read_buf[511] - network->__read_cursor;
- //Fill the rest of the buffer with data from the server, record how much was received
- network->__last_recv_len = recv(network->__socket, network->__read_cursor, space_left, MSG_DONTWAIT);
- //Find the end of the message
- eom = strstr(network->__read_cursor, "\r\n");
- //If we still can't find the end of the message, it's longer then 512 bytes, bail out!
- if (eom == NULL) {
- errno = EMSGSIZE;
- return -1;
- }
- //Calculate the length of the message
- size_t msg_len = eom - (char*)&network->__read_buf;
- //Store the message in res and null terminate it
- strncpy(res, &network->__read_buf, msg_len);
- res[msg_len + 1] = '\0';
- //If we received more data then that message then update cursor and indicate it within network
- if (msg_len < (network->__last_recv_len - 2)) {
- network->__read_cursor = &network->__read_buf[msg_len + 3];
- network->__data_waiting = true;
- }
- else {
- //Set cursor to beginning and indicate there is no data waiting
- network->__read_cursor = &network->__read_buf[0];
- network->__data_waiting = false;
- }
- return 0;
- }
- //Calculate the length of the message
- size_t msg_len = eom - (char*)&network->__read_buf;
- //Store message in res and null terminate it
- strncpy(res, network->__read_cursor, msg_len);
- res[msg_len + 1] = '\0';
- //Update cursor position
- network->__read_cursor = network->__read_cursor + msg_len + 2;
- //Check if there are still messages waiting on the buffer, if so indicate it within network
- network->__data_waiting = (network->__read_cursor - (char*)&network->__read_buf) < network->__last_recv_len;
- return 0;
- }
- //Fill the buffer with data from the server and record the length
- network->__last_recv_len = recv(network->__socket, &network->__read_buf, 512, 0);
- int errnono = errno;
- if (network->__last_recv_len = 0) { //If we receive no data, bail out
- errno = ENOMSG;
- return -1;
- }
- //Get the end of the message
- char * eom = strstr(&network->__read_buf, "\r\n"); //End Of Message
- //If we can't find it, the message is larger then 512 bytes, bail out
- if (eom == NULL) {
- errno = EMSGSIZE;
- return -1;
- }
- //Calculate the length of the message
- size_t msg_len = eom - (char*)&network->__read_buf;
- //Put the message in res and null terminate it
- strncpy(res, &network->__read_buf, msg_len);
- res[msg_len + 1] = '\0';
- //If the message size plus the \r\n pair is shorter then the data we received, there's more messages in the buffer
- if((msg_len + 2) < network->__last_recv_len) {
- network->__data_waiting = true;
- network->__read_cursor = &network->__read_buf[msg_len + 3];
- }
- return 0;
- }
- void irc_disconnect(struct irc_network * network) {
- close(network->__socket);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement