Main Page | File List

# /home/jared/lsdmake/src/socket.h

    00001 /*
    00002  *  socket.h
    00003  *  Liq's Standard Library.
    00004  *
    00005  *  Created by Freddie Gutierrez on Sun Dec 19 2004.
    00006  *  Copyright (c) 2004 Freddie Gutierrez. All rights reserved.
    00007  *
    00008  */
    00009
    00010 /*
    00011 How to set blocking after setting non-blocking.
    00012 <JeremyC> Liquidice: flags = fcntl(sock, F_GETFL);
    00013 <JeremyC> flags &= ~O_NONBLOCK;
    00014 <JeremyC> fcntl(sock, F_SETFL, flags);
    00015 */
    00016
    00017 /* Declare function prototypes. */
    00018 int sock_connect(unsigned ip, unsigned short port);
    00019 void *memstr(const void *s1, size_t l1, const void *s2, size_t l2);
    00020 int scknread2(int sck, char *result, unsigned int to_read);
    00021 int sock_write(int sockfd, char *str);
    00022 int sock_close(int sockfd);
    00023 void Disconnect(int sockfd);
    00024 bool Connect(int &sockfd, const char *ip);
    00025
    00026
    00027 bool Connect(int &sockfd, const char *ip) {
    00028         struct in_addr ipaddr;
    00029
    00030
    00031         memset(&ipaddr, 0, sizeof(in_addr));
    00032
    00033         if (inet_aton(ip, &ipaddr)) {
    00034                 sockfd = sock_connect(ipaddr.s_addr, 80);
    00035
    00036                 if (sockfd == -1)
    00037                         printf("Error: Could not open socket.\n");
    00038                 else if (sockfd == -2)
    00039                         printf("Error: Could not make connection.\n");
    00040                 else
    00041                         return true;
    00042         }
    00043
    00044         return false;
    00045 }
    00046
    00047 void Disconnect(int sockfd) {
    00048         sock_close(sockfd);
    00049 }
    00050
    00051 int sock_connect(unsigned ip, unsigned short port) {
    00052
    00053         int sockfd; //sockfd = Socket File Descriptor
    00054         struct sockaddr_in serv_addr;
    00055
    00056
    00057         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    00058                 //fprintf(stderr, "ERROR opening socket\n");
    00059                 return -1;
    00060         } else {
    00061                 memset(&serv_addr, 0, sizeof(serv_addr)); //fill in the memory with zeros
    00062                 serv_addr.sin_family = AF_INET;
    00063                 serv_addr.sin_addr.s_addr = ip;
    00064                 serv_addr.sin_port = htons(port);
    00065
    00066                 if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) {
    00067                         //fprintf(stderr,"ERROR connecting\n");
    00068                         close(sockfd); //No connection could be made, so close the socket's file descriptor.
    00069                         return -2;
    00070                 }
    00071         }
    00072         return sockfd; //w00t we're connected, so set the result to the file descriptor :D
    00073 }
    00074
    00075 bool sock_is_connected(int sockfd, unsigned int ip, unsigned short port) {
    00076         struct sockaddr_in serv_addr;
    00077
    00078         memset(&serv_addr, 0, sizeof(serv_addr));
    00079         serv_addr.sin_family = AF_INET;
    00080         serv_addr.sin_addr.s_addr = ip;
    00081         serv_addr.sin_port = htons(port);
    00082
    00083         connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
    00084
    00085         if (errno == EISCONN)
    00086                 return true;
    00087
    00088         return false;
    00089 }
    00090
    00091 char *sock_readall(int sockfd) {
    00092         char *result, *tmp, *buffer[102400];
    00093         int bytesread, lenlast, lentotal;
    00094         struct pollfd wait;
    00095
    00096
    00097         wait.fd = sockfd;
    00098         wait.events = POLLIN;
    00099         result = tmp = NULL;
    00100         bytesread = lenlast = lentotal = 0;
    00101
    00102
    00103         //printf("Initial Poll()...\n");
    00104         fflush(stdout);
    00105
    00106         /* Initial wait is 60 seconds. */
    00107         if (poll(&wait, 1, 60000) == 1) { /* wait up to 60 seconds for data to become available */
    00108                 //puts("Reading...");
    00109                 fflush(stdout);
    00110                 bytesread = recv(sockfd, buffer, 102400, MSG_WAITALL);
    00111                 //printf("Read %d bytes. err = %i : %s\n", bytesread, errno, strerror(errno));
    00112
    00113                 if (bytesread > 0) {
    00114
    00115                         result = (char *) malloc(lentotal + bytesread);
    00116                         if (result == NULL)
    00117                                 return NULL;
    00118                         memcpy(result+lentotal, buffer, bytesread);
    00119                         lentotal += bytesread;
    00120                 }
    00121
    00122         } else {
    00123                 //puts("sock_readall: Timed out while waiting for a response.");
    00124         }
    00125
    00126         /* If we received any data, check if there's anymore, But don't wait as long. */
    00127         while(bytesread > 0) {
    00128
    00129                 lenlast = bytesread;
    00130                 bytesread = 0;
    00131                 //printf("Poll()...\n");
    00132                 fflush(stdout);
    00133
    00134                 if (poll(&wait, 1, 5000) == 1) { /* wait up to 5 seconds for data to become available */
    00135                         //puts("Reading...");
    00136                         fflush(stdout);
    00137                         bytesread = recv(sockfd, buffer, 102400, MSG_WAITALL);
    00138                         //printf("Read %d bytes. err = %i : %s\n", bytesread, errno, strerror(errno));
    00139
    00140                         if (bytesread > 0) {
    00141                                 /* Safe realloc. */
    00142                                 tmp = (char *) realloc(result, (lentotal + bytesread));
    00143                                 if (tmp == NULL) {
    00144                                         free(result);
    00145                                         return NULL;
    00146                                 }
    00147                                 result = tmp;
    00148
    00149                                 memcpy(result+lentotal, buffer, bytesread);
    00150                                 lentotal += bytesread;
    00151                         } else
    00152                                 break;
    00153
    00154                 } else {
    00155                         puts("sock_readall: Timed out while waiting for a response.");
    00156                         break;
    00157                 }
    00158         }
    00159
    00160         /* Safe realloc. */
    00161         tmp = (char *) realloc(result, lentotal+1);
    00162         if (tmp == NULL) {
    00163                 free(result);
    00164                 return NULL;
    00165         }
    00166         result = tmp;
    00167
    00168         result[lentotal] = '\0';
    00169
    00170         return result;
    00171 }
    00172
    00173
    00174 //buffer must have enough room for result_len + halt_str_len
    00175 int sckstrstr(int sockfd, char *result, size_t b_size, const char *halt_str) {
    00176         unsigned int halt_str_len, total_len, reads;
    00177         int this_read;
    00178         char *str_ptr;
    00179
    00180
    00181         total_len = reads = 0;
    00182         halt_str_len = strlen(halt_str);
    00183
    00184         do {
    00185                 this_read = recv(sockfd, result+total_len, b_size - total_len, 0);
    00186                 if (this_read > 0) {
    00187                         total_len += this_read;
    00188                         //if ((str_ptr = memstr(result, total_len,
    00189                         //                                        halt_str, halt_str_len)) != NULL) {
    00190                                 str_ptr[halt_str_len - 1] = 0;
    00191
    00192                                 total_len = (unsigned int) ((str_ptr+halt_str_len) - result);
    00193                                 break;
    00194                         //}
    00195                 } else {
    00196                         if (this_read == 0)
    00197                                 printf("Read 0\n");
    00198                         else
    00199                                 printf("recv(): %s\n", strerror(errno));
    00200                         break;
    00201                 }
    00202         } while(total_len < b_size);
    00203
    00204         /* TODO: clear socket buffer. */
    00205
    00206         return total_len;
    00207 }
    00208
    00209 /* TODO: clear socket buffer once done recv'ing unless you're going to
    00210 close() the socket. */
    00211 int sckssto(int sck, char *result, size_t b_size, const char *halt_str, float timeout) {
    00212         unsigned int halt_str_len, total_len, reads;
    00213         int select_result, this_read;
    00214         char *str_ptr;
    00215         struct timeval tv;
    00216         fd_set rfds;
    00217
    00218         total_len = reads = 0;
    00219         halt_str_len = strlen(halt_str);
    00220         FD_ZERO(&rfds);
    00221         FD_SET(sck, &rfds);
    00222
    00223
    00224         do {
    00225                 printf("Waiting.\n");
    00226                 tv.tv_sec = (int) timeout;
    00227                 tv.tv_usec = (int) (timeout - (float) tv.tv_sec) * 1000;
    00228                 select_result = select(sck+1, &rfds, NULL, NULL, &tv);
    00229                 printf("time's up sck = %i fd_set = %lu\n",
    00230                            FD_ISSET(sck, &rfds), sizeof(fd_set));
    00231                 if (select_result == -1 && errno == EINTR)
    00232                         continue;
    00233
    00234                 if (select_result > 0) {
    00235                         printf("Reading.\n");
    00236                         this_read = recv(sck, result+total_len, b_size - total_len, 0);
    00237
    00238                         if (this_read) {
    00239                                 total_len += this_read;
    00240                                 /* BUG: if only half of the halt_str is recv'd memstr
    00241                                 will never beable to locate it because we've set the
    00242                                 pointer past it. */
    00243                                 //if ((str_ptr = memstr(result+(total_len-this_read), this_read,
    00244                                 //                                        halt_str, halt_str_len)) != NULL) {
    00245                                         printf("Got %i/%c\n", (int) *(str_ptr+halt_str_len), (char) *(str_ptr+halt_str_len));
    00246                                         str_ptr[halt_str_len] = 0;
    00247                                         total_len += strlen(result+(total_len - this_read)) - this_read;
    00248                                         break;
    00249                                 //}
    00250                         } else {
    00251                                 if (this_read == -1)
    00252                                         return -1;
    00253                                 break;
    00254                         }
    00255                 } else {
    00256                         errno = ETIMEDOUT;
    00257                         return -1;
    00258                 }
    00259         } while(total_len < b_size);
    00260
    00261         return total_len;
    00262 }
    00263
    00264 int scknstr_timeout(int sck, char *result, size_t b_size, const char *halt_str, short timeout) {
    00265         unsigned int halt_str_len, total_len = 0;
    00266         int this_read, select_result;
    00267         char *str_ptr;
    00268         struct timeval tv;
    00269         fd_set rfds;
    00270
    00271
    00272         /* Find length of halt string */
    00273         halt_str_len = strlen(halt_str);
    00274
    00275         /* Prepare our fd_set to watch for incoming data. */
    00276         FD_ZERO(&rfds);
    00277         FD_SET(sck, &rfds);
    00278
    00279         /* Set timeout */
    00280         tv.tv_sec = timeout;
    00281         tv.tv_usec = 0;
    00282
    00283         do {
    00284                 /* Wait for data to become available */
    00285                 select_result = select(sck+1, &rfds, NULL, NULL, &tv);
    00286
    00287                 /* If our select was interupted, re-start the loop. */
    00288                 if (select_result == -1 && errno == EINTR)
    00289                         continue;
    00290
    00291                 if (select_result > 0) {
    00292                         this_read = recv(sck, result+total_len, b_size - total_len, 0);
    00293                         if (this_read > 0) {
    00294                                 total_len += this_read;
    00295                                 /* Search for halt string, if found, nul terminate
    00296                                 buffer, correct total_len and break out of loop. */
    00297                                 //if ((str_ptr = memstr(result, total_len,
    00298                                 //                                        halt_str, halt_str_len)) != NULL) {
    00299                                         str_ptr[halt_str_len] = 0;
    00300                                         total_len += strlen(result+(total_len - this_read)) - this_read;
    00301                                         break;
    00302                         //      }
    00303                         } else {
    00304                                 /* if recv() error, return and exit function */
    00305                                 if (this_read == -1)
    00306                                         return -1;
    00307                                 /* recv() read 0 so break and return total read bytes */
    00308                                 break;
    00309                         }
    00310                 } else {
    00311                         /* select timed out, no data available */
    00312                         errno = ETIMEDOUT;
    00313                         return -1;
    00314                 }
    00315         } while(total_len < b_size);
    00316
    00317         return total_len;
    00318 }
    00319
    00320 void *memstr(const void *s1, size_t l1, const void *s2, size_t l2) {
    00321
    00322         if (l1 || l2)
    00323                 while (l1 >= l2) {
    00324                         l1--;
    00325                         if (!memcmp(s1,s2,l2))
    00326                                 return (void *) s1;
    00327                         ((char *) s1)++;
    00328                 }
    00329
    00330         return NULL;
    00331 }
    00332
    00333 int sock_write(int sockfd, char *str) {
    00334         if (send(sockfd, str, strlen(str), 0)) {
    00335                 return true;
    00336         } else {
    00337
    00338                 fprintf(stderr, "sock_write: %s", strerror(errno));
    00339                 return false;
    00340         }
    00341         //return (send(sockfd, str, strlen(str), 0)) ? 1 : 0;
    00342 }
    00343
    00344 int sock_close(int sockfd) {
    00345         return (close(sockfd) == 0) ? 1 : 0;
    00346 }