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 }

Generated on Fri Jul 8 14:31:05 2005 for lsdmake.kdevelop by doxygen 1.3.8