Advertisement
Lyude

Untitled

Mar 16th, 2012
39
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.40 KB | None | 0 0
  1. //Contains the functions the bot uses to connect
  2.  
  3. #include <string.h>     //For String functions
  4. #include <stdio.h>  //For standard input/output
  5. #include <errno.h>  //For errors
  6.  
  7. //Needed for getaddrinfo(), socket(), etc.
  8. #include <sys/types.h>
  9. #include <sys/socket.h>
  10. #include <netdb.h>
  11.  
  12. #include "netstructs.h" //Contains the data structures used for connections
  13.  
  14. #include "connect.h"
  15.  
  16. int irc_connect(struct irc_network * network) {
  17.     struct addrinfo hints; //Hints for getaddrinfo()
  18.     struct addrinfo * results; //Points to the results from getaddrinfo()
  19.  
  20.     //Clean the hints structure
  21.     memset(&hints, '\0', sizeof(struct addrinfo));
  22.  
  23.     //Set up hints structure
  24.     hints.ai_family = AF_UNSPEC;    //Can be IPv4 or 6
  25.     hints.ai_socktype = SOCK_DGRAM; //Datagram socket
  26.     hints.ai_flags = 0;
  27.     hints.ai_protocol = 0;      //Any protocol
  28.  
  29.     //Attempt to connect using the information provided in network
  30.     if (getaddrinfo(network->hostname, network->port, &hints, &results) != 0)
  31.         return -1;
  32.    
  33.     //Loop through the list of address structures returned by getaddrinfo until we connect
  34.     struct addrinfo * cur; //Points to the structure we're currently trying
  35.     for (cur = results; cur != NULL; cur = cur->ai_next) {
  36.         //Attempt to make socket
  37.         network->__socket = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
  38.  
  39.         //If it fails, go back to the beggining and try with the next structure
  40.         if (network->__socket == -1)
  41.             continue;
  42.  
  43.         //If it doesn't, then attempt to connect, if that works then we're done here
  44.         if (connect(network->__socket, cur->ai_addr, cur->ai_addrlen) != -1)
  45.             break;
  46.  
  47.         //It didn't work, so we'll close the socket and go back to the beginning
  48.         close(network->__socket);
  49.     }
  50.  
  51.     //Check if we connected, if not return an error
  52.     if (cur == NULL)
  53.         return -1;
  54.    
  55.     //We don't need the results anymore, so free the allocated memory
  56.     freeaddrinfo(results);
  57.  
  58.     //Send our nickname information to the server
  59.     char msgbuf[512]; //512 is the standard maximum length of an IRC message
  60.    
  61.     snprintf(&msgbuf, 512, "NICK %s\r\n", network->nickname);
  62.     send(network->__socket, &msgbuf, strlen(&msgbuf), 0);
  63.  
  64.     //Now send our user info to the server
  65.     snprintf(&msgbuf, 512, "USER %s %s %s :%s\r\n",
  66.         network->username, network->user_hostname, network->hostname, network->realname);
  67.     send(network->__socket, &msgbuf, strlen(&msgbuf), 0);
  68.  
  69.     //Before we indicate we've finished, we want to make sure the network structure and cursor are initialized
  70.     network->__read_cursor = &network->__read_buf[0];   //Set the cursor at the beggining of the buffer
  71.     memset(&network->__read_buf, '\0', 513);        //Clean the read buffer
  72.     network->__read_buf[512] = '\0';            //Set the last character in the buffer to a null byte
  73.     network->__data_waiting = false;            //Indicate there's no data in the buffer yet
  74.    
  75.     //Information sent, if all went well we should be connected!
  76.     return 0;
  77. }
  78.  
  79. int __irc_read(struct irc_network * network, char * res) {
  80.     //Check if there are still messages waiting to be parsed in __read_buf
  81.     if (network->__data_waiting) {
  82.         //Figure out how much space we have left in the buffer after the cursor
  83.         size_t space_left = &network->__read_buf[511] - network->__read_cursor;
  84.  
  85.         //Find the end of the next message
  86.         char * eom = strstr(network->__read_cursor, "\r\n"); //End Of Message
  87.  
  88.         if (eom == NULL) { //If only a partially completed message is found
  89.             //Move the current message to the front of the buffer
  90.             memmove(&network->__read_buf, network->__read_cursor, space_left);
  91.            
  92.             //Update the cursor, and recalculate space_left
  93.             network->__read_cursor = &network->__read_buf[space_left];
  94.             space_left = &network->__read_buf[511] - network->__read_cursor;
  95.  
  96.             //Fill the rest of the buffer with data from the server, record how much was received
  97.             network->__last_recv_len = recv(network->__socket, network->__read_cursor, space_left, MSG_DONTWAIT);
  98.  
  99.             //Find the end of the message
  100.             eom = strstr(network->__read_cursor, "\r\n");
  101.  
  102.             //If we still can't find the end of the message, it's longer then 512 bytes, bail out!
  103.             if (eom == NULL) {
  104.                 errno = EMSGSIZE;
  105.                 return -1;
  106.             }
  107.  
  108.             //Calculate the length of the message
  109.             size_t msg_len = eom - (char*)&network->__read_buf;
  110.  
  111.             //Store the message in res and null terminate it
  112.             strncpy(res, &network->__read_buf, msg_len);
  113.             res[msg_len + 1] = '\0';
  114.  
  115.             //If we received more data then that message then update cursor and indicate it within network
  116.             if (msg_len < (network->__last_recv_len - 2)) {
  117.                 network->__read_cursor = &network->__read_buf[msg_len + 3];
  118.                 network->__data_waiting = true;
  119.             }
  120.             else {
  121.                 //Set cursor to beginning and indicate there is no data waiting
  122.                 network->__read_cursor = &network->__read_buf[0];
  123.                 network->__data_waiting = false;
  124.             }
  125.  
  126.             return 0;
  127.         }
  128.  
  129.         //Calculate the length of the message
  130.         size_t msg_len = eom - (char*)&network->__read_buf;
  131.  
  132.         //Store message in res and null terminate it
  133.         strncpy(res, network->__read_cursor, msg_len);
  134.         res[msg_len + 1] = '\0';
  135.  
  136.         //Update cursor position
  137.         network->__read_cursor = network->__read_cursor + msg_len + 2;
  138.  
  139.         //Check if there are still messages waiting on the buffer, if so indicate it within network
  140.         network->__data_waiting = (network->__read_cursor - (char*)&network->__read_buf) < network->__last_recv_len;
  141.  
  142.         return 0;
  143.     }
  144.  
  145.     //Fill the buffer with data from the server and record the length
  146.     network->__last_recv_len = recv(network->__socket, &network->__read_buf, 512, 0);
  147.     int errnono = errno;
  148.     if (network->__last_recv_len = 0) { //If we receive no data, bail out
  149.         errno = ENOMSG;
  150.         return -1;
  151.     }
  152.  
  153.     //Get the end of the message
  154.     char * eom = strstr(&network->__read_buf, "\r\n"); //End Of Message
  155.    
  156.     //If we can't find it, the message is larger then 512 bytes, bail out
  157.     if (eom == NULL) {
  158.         errno = EMSGSIZE;
  159.         return -1;
  160.     }
  161.  
  162.     //Calculate the length of the message
  163.     size_t msg_len = eom - (char*)&network->__read_buf;
  164.    
  165.     //Put the message in res and null terminate it
  166.     strncpy(res, &network->__read_buf, msg_len);
  167.     res[msg_len + 1] = '\0';
  168.  
  169.     //If the message size plus the \r\n pair is shorter then the data we received, there's more messages in the buffer
  170.     if((msg_len + 2) < network->__last_recv_len) {
  171.         network->__data_waiting = true;
  172.         network->__read_cursor = &network->__read_buf[msg_len + 3];
  173.     }
  174.  
  175.     return 0;
  176. }
  177.  
  178. void irc_disconnect(struct irc_network * network) {
  179.     close(network->__socket);
  180. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement