1 /**
2  * SIEGE socket library
3  *
4  * Copyright (C) 2000-2015 by
5  * Jeffrey Fulmer - <jeff@joedog.org>, et al.
6  * This file is distributed as part of Siege
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 #ifdef  HAVE_CONFIG_H
24 # include <config.h>
25 #endif/*HAVE_CONFIG_H*/
26 
27 #include <setup.h>
28 #include <sock.h>
29 #include <util.h>
30 #include <memory.h>
31 #include <notify.h>
32 #include <joedog/boolean.h>
33 #include <joedog/defs.h>
34 #include <pthread.h>
35 #include <fcntl.h>
36 
37 #ifdef HAVE_POLL
38 # include <poll.h>
39 #endif/*HAVE_POLL*/
40 
41 #ifdef  HAVE_UNISTD_H
42 # include <unistd.h>
43 #endif/*HAVE_UNISTD_H*/
44 
45 #ifdef  HAVE_ARPA_INET_H
46 # include <arpa/inet.h>
47 #endif/*HAVE_ARPA_INET_H*/
48 
49 #ifdef  HAVE_SYS_SOCKET_H
50 # include <sys/socket.h>
51 #endif/*HAVE_SYS_SOCKET_H*/
52 
53 #ifdef  HAVE_NETINET_IN_H
54 # include <netinet/in.h>
55 #endif/*HAVE_NETINET_IN_H*/
56 
57 #ifdef  HAVE_NETDB_H
58 # include <netdb.h>
59 #endif/*HAVE_NETDB_H*/
60 
61 #ifdef  HAVE_SSL
62 # include <openssl/rand.h>
63 #endif/*HAVE_SSL*/
64 
65 #define MAX_PORT_NO 65535
66 
67 /**
68  * local prototypes
69  */
70 private int     __socket_block(int socket, BOOLEAN block);
71 private ssize_t __socket_write(int sock, const void *vbuf, size_t len);
72 private BOOLEAN __socket_check(CONN *C, SDSET mode);
73 private BOOLEAN __socket_select(CONN *C, SDSET mode);
74 private int     __socket_create(CONN *C, int domain);
75 private void   __hostname_strip(char *hn, int len);
76 #ifdef  HAVE_POLL
77 private BOOLEAN __socket_poll(CONN *C, SDSET mode);
78 #endif/*HAVE_POLL*/
79 #ifdef  HAVE_SSL
80 private ssize_t __ssl_socket_write(CONN *C, const void *vbuf, size_t len);
81 #endif/*HAVE_SSL*/
82 
83 /**
84  * new_socket
85  * returns int, socket handle
86  */
87 int
new_socket(CONN * C,const char * hostparam,int portparam)88 new_socket(CONN *C, const char *hostparam, int portparam)
89 {
90   int conn;
91   int res;
92   int addrlen;
93   struct sockaddr *s_addr;
94   char   hn[512];
95   int    port;
96   int    domain;
97 #if defined(__GLIBC__)
98   char port_str[10];
99   struct addrinfo hints;
100   struct addrinfo *addr_res;
101   struct addrinfo *r;
102 #else
103   struct sockaddr_in cli;
104   struct hostent     *hp;
105   int herrno;
106 #endif
107 #if defined(sun)
108 # ifndef HAVE_GETIPNODEBYNAME
109   struct hostent hent;
110   char hbf[8192];
111 # endif/*HAVE_GETIPNODEBYNAME*/
112 #elif defined(_AIX)
113   char *aixbuf;
114   int  rc;
115 #endif/*_AIX*/
116 
117   if (hostparam == NULL) {
118     NOTIFY(ERROR, "Unable to resolve host %s:%d",  __FILE__, __LINE__);
119     return -1;
120   }
121 
122   C->encrypt  = (C->scheme == HTTPS) ? TRUE: FALSE;
123   C->state    = UNDEF;
124   C->ftp.pasv = TRUE;
125   C->ftp.size = 0;
126 
127   memset(hn, '\0', sizeof hn);
128 
129   /* if we are using a proxy, then we make a socket
130      connection to that server rather then a httpd */
131   if (auth_get_proxy_required(my.auth)) {
132     snprintf(hn, sizeof(hn), "%s", auth_get_proxy_host(my.auth));
133     port = auth_get_proxy_port(my.auth);
134   } else {
135     snprintf(hn, sizeof(hn), "%s", hostparam);
136     port = portparam;
137   }
138   __hostname_strip(hn, 512);
139 
140   /* sanity check */
141   if (port < 1 || port > MAX_PORT_NO) {
142     NOTIFY(ERROR, "invalid port number %d in %s:%d", port, __FILE__, __LINE__);
143     return -1;
144   }
145 
146 #if defined(__GLIBC__)
147   {
148     snprintf(port_str, sizeof(port_str), "%d", port);
149 
150     /* hints for address lookup */
151     memset(&hints, 0, sizeof(struct addrinfo));
152     hints.ai_family=AF_UNSPEC;
153     hints.ai_socktype=SOCK_STREAM;
154     hints.ai_protocol=IPPROTO_TCP;
155 
156     res = getaddrinfo(hn, port_str, &hints, &addr_res);
157     if (res != 0) {
158       NOTIFY(ERROR, "Address resolution failed at %s:%d with the following error:", __FILE__, __LINE__);
159       NOTIFY(ERROR, "%s", gai_strerror(res));
160       return -1;
161     }
162     s_addr = addr_res->ai_addr;
163     addrlen = addr_res->ai_addrlen;
164     domain = addr_res->ai_family;
165   }
166 #elif defined(sun) || defined(__FreeBSD__)
167 # ifdef HAVE_GETIPNODEBYNAME
168   hp = getipnodebyname(hn, AF_INET, 0, &herrno);
169 # else /* default use gethostbyname_r*/
170   {
171     memset(hbf, '\0', sizeof hbf);
172     hp = gethostbyname_r(hn, &hent, hbf, sizeof(hbf), &herrno);
173   }
174 # endif/*HAVE_GETIPNODEBYNAME*/
175 #elif defined(_AIX)
176   aixbuf = (char*)xmalloc(8192);
177   rc  = gethostbyname_r(hn, (struct hostent *)aixbuf,
178                        (struct hostent_data *)(aixbuf + sizeof(struct hostent)));
179   hp = (struct hostent*)aixbuf;
180 #elif (defined(hpux) || defined(__hpux) || defined(__osf__))
181   hp = gethostbyname(hn);
182   herrno = h_errno;
183 #else
184   /**
185    * Let's just hope gethostbyname is tread-safe
186    */
187   hp = gethostbyname(hn);
188   herrno = h_errno;
189 #endif/*OS SPECIFICS*/
190 
191 #if !defined(__GLIBC__)
192   /* gethostbyname only offers IPv4 support */
193   domain = AF_INET;
194 
195   /**
196    * If hp is NULL, then we did not get good information
197    * from the name server. Let's notify the user and bail
198    */
199   if (hp == NULL) {
200     switch(herrno) {
201       case HOST_NOT_FOUND: { NOTIFY(ERROR, "Host not found: %s\n", hostparam);                           break; }
202       case NO_ADDRESS:     { NOTIFY(ERROR, "Host does not have an IP address: %s\n", hostparam);         break; }
203       case NO_RECOVERY:    { NOTIFY(ERROR, "A non-recoverable resolution error for %s\n", hostparam);    break; }
204       case TRY_AGAIN:      { NOTIFY(ERROR, "A temporary resolution error for %s\n", hostparam);          break; }
205       default:             { NOTIFY(ERROR, "Unknown error code from gethostbyname for %s\n", hostparam); break; }
206     }
207     return -1;
208   }
209 
210   memset((void*) &cli, 0, sizeof(cli));
211   memcpy(&cli.sin_addr, hp->h_addr, hp->h_length);
212 #if defined(sun) || defined(__FreeBSD__)
213 # ifdef  HAVE_FREEHOSTENT
214   freehostent(hp);
215 # endif/*HAVE_FREEHOSTENT*/
216 #endif
217   cli.sin_family = AF_INET;
218   cli.sin_port = htons(port);
219 
220   s_addr = (struct sockaddr *)&cli;
221   addrlen = sizeof(struct sockaddr_in);
222 #endif /* end of __GLIBC__ not defined */
223 
224   /* create a socket, return -1 on failure */
225   if (__socket_create(C, domain) < 0) {
226     return -1;
227   }
228 
229   /**
230    * connect to the host
231    * evaluate the server response and check for
232    * readability/writeability of the socket....
233    */
234   conn = connect(C->sock, s_addr, addrlen);
235   pthread_testcancel();
236 #if defined(__GLIBC__)
237   /**
238     * The result of getaddrinfo is a linked list. Attempt
239     * to connect to each result until successful
240     */
241   if (conn < 0 && errno != EINPROGRESS) {
242     addr_res = addr_res->ai_next;
243     for (r = addr_res; r; r = r->ai_next) {
244       /* close previously opened socket */
245       socket_close(C);
246 
247       /* create a socket, return -1 on failure */
248       if (__socket_create(C, domain) < 0) {
249         return -1;
250       }
251 
252       conn = connect(C->sock, s_addr, addrlen);
253       pthread_testcancel();
254       if (conn == 0) {
255         break;
256       }
257     }
258   }
259 #endif
260   if (conn < 0 && errno != EINPROGRESS) {
261     switch (errno) {
262       case EACCES:        {NOTIFY(ERROR, "socket: %d EACCES",                  pthread_self()); break;}
263       case EADDRNOTAVAIL: {NOTIFY(ERROR, "socket: %d address is unavailable.", pthread_self()); break;}
264       case ETIMEDOUT:     {NOTIFY(ERROR, "socket: %d connection timed out.",   pthread_self()); break;}
265       case ECONNREFUSED:  {NOTIFY(ERROR, "socket: %d connection refused.",     pthread_self()); break;}
266       case ENETUNREACH:   {NOTIFY(ERROR, "socket: %d network is unreachable.", pthread_self()); break;}
267       case EISCONN:       {NOTIFY(ERROR, "socket: %d already connected.",      pthread_self()); break;}
268       default:            {NOTIFY(ERROR, "socket: %d unknown network error.",  pthread_self()); break;}
269     } socket_close(C); return -1;
270   } else {
271     if (__socket_check(C, READ) == FALSE) {
272       pthread_testcancel();
273       NOTIFY(WARNING, "socket: read check timed out(%d) %s:%d", my.timeout, __FILE__, __LINE__);
274       socket_close(C);
275       return -1;
276     } else {
277       /**
278        * If we reconnect and receive EISCONN, then we have a successful connection
279        */
280       res = connect(C->sock, s_addr, addrlen);
281       if((res < 0)&&(errno != EISCONN)){
282         NOTIFY(ERROR, "socket: unable to connect %s:%d", __FILE__, __LINE__);
283         socket_close(C);
284         return -1;
285       }
286       C->status = S_READING;
287     }
288   } /* end of connect conditional */
289 
290   if ((__socket_block(C->sock, TRUE)) < 0) {
291     NOTIFY(ERROR, "socket: unable to set socket to non-blocking %s:%d", __FILE__, __LINE__);
292     return -1;
293   }
294 
295   C->connection.status = 1;
296   return(C->sock);
297 }
298 
299 /**
300  * Conditionally determines whether or not a socket is ready.
301  * This function calls __socket_poll if HAVE_POLL is defined in
302  * config.h, else it uses __socket_select
303  */
304 private BOOLEAN
__socket_check(CONN * C,SDSET mode)305 __socket_check(CONN *C, SDSET mode)
306 {
307 #ifdef HAVE_POLL
308  if (C->sock >= FD_SETSIZE) {
309    return __socket_poll(C, mode);
310  } else {
311    return __socket_select(C, mode);
312  }
313 #else
314  return __socket_select(C, mode);
315 #endif/*HAVE_POLL*/
316 }
317 
318 #ifdef HAVE_POLL
319 private BOOLEAN
__socket_poll(CONN * C,SDSET mode)320 __socket_poll(CONN *C, SDSET mode)
321 {
322   int res;
323   int timo = (my.timeout) ? my.timeout * 1000 : 15000;
324   __socket_block(C->sock, FALSE);
325 
326   C->pfd[0].fd     = C->sock + 1;
327   C->pfd[0].events |= POLLIN;
328 
329   do {
330     res = poll(C->pfd, 1, timo);
331     pthread_testcancel();
332     if (res < 0) puts("LESS THAN ZERO!");
333   } while (res < 0); // && errno == EINTR);
334 
335   if (res == 0) {
336     errno = ETIMEDOUT;
337   }
338 
339   if (res <= 0) {
340     C->state = UNDEF;
341     NOTIFY(WARNING,
342       "socket: polled(%d) and discovered it's not ready %s:%d",
343       (my.timeout)?my.timeout:15, __FILE__, __LINE__
344     );
345     return FALSE;
346   } else {
347     C->state = mode;
348     return TRUE;
349   }
350 }
351 #endif/*HAVE_POLL*/
352 
353 private BOOLEAN
__socket_select(CONN * C,SDSET mode)354 __socket_select(CONN *C, SDSET mode)
355 {
356   struct timeval timeout;
357   int    res;
358   fd_set rs;
359   fd_set ws;
360   memset((void *)&timeout, '\0', sizeof(struct timeval));
361   timeout.tv_sec  = (my.timeout > 0)?my.timeout:30;
362   timeout.tv_usec = 0;
363 
364   if ((C->sock < 0) || (C->sock >= FD_SETSIZE)) {
365     // FD_SET can't handle it
366     return FALSE;
367   }
368 
369   do {
370     FD_ZERO(&rs);
371     FD_ZERO(&ws);
372     FD_SET(C->sock, &rs);
373     FD_SET(C->sock, &ws);
374     res = select(C->sock+1, &rs, &ws, NULL, &timeout);
375     pthread_testcancel();
376   } while (res < 0 && errno == EINTR);
377 
378   if (res == 0) {
379     errno = ETIMEDOUT;
380   }
381 
382   if (res <= 0) {
383     C->state = UNDEF;
384     NOTIFY(WARNING, "socket: select and discovered it's not ready %s:%d", __FILE__, __LINE__);
385     return FALSE;
386   } else {
387     C->state = mode;
388     return TRUE;
389   }
390 }
391 
392 /**
393  * Create new socket and set socket options.
394  * Handle possible error codes.
395  */
396 private int
__socket_create(CONN * C,int domain)397 __socket_create(CONN *C, int domain)
398 {
399   if ((C->sock = socket(domain, SOCK_STREAM, 0)) < 0) {
400     switch (errno) {
401       case EPROTONOSUPPORT: { NOTIFY(ERROR, "unsupported protocol %s:%d",  __FILE__, __LINE__); break; }
402       case EMFILE:          { NOTIFY(ERROR, "descriptor table full %s:%d", __FILE__, __LINE__); break; }
403       case ENFILE:          { NOTIFY(ERROR, "file table full %s:%d",       __FILE__, __LINE__); break; }
404       case EACCES:          { NOTIFY(ERROR, "permission denied %s:%d",     __FILE__, __LINE__); break; }
405       case ENOBUFS:         { NOTIFY(ERROR, "insufficient buffer %s:%d",   __FILE__, __LINE__); break; }
406       default:              { NOTIFY(ERROR, "unknown socket error %s:%d",  __FILE__, __LINE__); break; }
407     } socket_close(C); return -1;
408   }
409   if (fcntl(C->sock, F_SETFD, O_NDELAY) < 0) {
410     NOTIFY(ERROR, "unable to set close control %s:%d", __FILE__, __LINE__);
411   }
412 
413   if (C->connection.keepalive) {
414     int opt = 1;
415     if (setsockopt(C->sock,SOL_SOCKET,SO_KEEPALIVE,(char *)&opt,sizeof(opt))<0) {
416       switch (errno) {
417         case EBADF:       { NOTIFY(ERROR, "invalid descriptor %s:%d",    __FILE__, __LINE__); break; }
418         case ENOTSOCK:    { NOTIFY(ERROR, "not a socket %s:%d",          __FILE__, __LINE__); break; }
419         case ENOPROTOOPT: { NOTIFY(ERROR, "not a protocol option %s:%d", __FILE__, __LINE__); break; }
420         case EFAULT:      { NOTIFY(ERROR, "setsockopt unknown %s:%d",    __FILE__, __LINE__); break; }
421         default:          { NOTIFY(ERROR, "unknown sockopt error %s:%d", __FILE__, __LINE__); break; }
422       } socket_close(C); return -1;
423     }
424   }
425 
426   if ((__socket_block(C->sock, FALSE)) < 0) {
427     NOTIFY(ERROR, "socket: unable to set socket to non-blocking %s:%d", __FILE__, __LINE__);
428     return -1;
429   }
430 
431   return 0;
432 }
433 
434 /**
435  * remove square bracket
436  * around IPv6 addresses
437  */
438 private void
__hostname_strip(char * hn,int len)439 __hostname_strip(char *hn, int len)
440 {
441   int i;
442 
443   if (startswith("[", hn)) {
444     memmove(hn, hn + 1, len - 1);
445 
446     /* skip to matching square bracket */
447     for (i = 0; hn[i] && hn[i] != ']'; i++);
448 
449     if (hn[i] == ']') {
450       memmove(hn + i, hn + i + 1, len - i - 1);
451     }
452   }
453 }
454 
455 /**
456  * local function
457  * set socket to non-blocking
458  */
459 private int
__socket_block(int sock,BOOLEAN block)460 __socket_block(int sock, BOOLEAN block)
461 {
462 #if HAVE_FCNTL_H
463   int flags;
464   int retval;
465 #elif defined(FIONBIO)
466   ioctl_t status;
467 #else
468   return sock;
469 #endif
470 // return sock;
471   if (sock==-1) {
472     return sock;
473   }
474 
475 #if HAVE_FCNTL_H
476   if ((flags = fcntl(sock, F_GETFL, 0)) < 0) {
477     switch (errno) {
478       case EACCES: { NOTIFY(ERROR, "EACCES %s:%d",                 __FILE__, __LINE__); break; }
479       case EBADF:  { NOTIFY(ERROR, "bad file descriptor %s:%d",    __FILE__, __LINE__); break; }
480       case EAGAIN: { NOTIFY(ERROR, "address is unavailable %s:%d", __FILE__, __LINE__); break; }
481       default:     { NOTIFY(ERROR, "unknown network error %s:%d",  __FILE__, __LINE__); break; }
482     } return -1;
483   }
484 
485   if (block) {
486     flags &= ~O_NDELAY;
487   } else {
488     flags |=  O_NDELAY;
489     #if (defined(hpux) || defined(__hpux) || defined(__osf__)) || defined(__sun)
490     #else
491     flags |=  O_NONBLOCK;
492     #endif
493   }
494 
495   if ((retval = fcntl(sock, F_SETFL, flags)) < 0) {
496     NOTIFY(ERROR, "unable to set fcntl flags %s:%d", __FILE__, __LINE__);
497     return -1;
498   }
499   return retval;
500 
501 #elif defined(FIONBIO)
502   status = block ? 0 : 1;
503   return ioctl(sock, FIONBIO, &status);
504 #endif
505 }
506 
507 /**
508  * returns ssize_t
509  * writes vbuf to sock
510  */
511 private ssize_t
__socket_write(int sock,const void * vbuf,size_t len)512 __socket_write(int sock, const void *vbuf, size_t len)
513 {
514   size_t      n;
515   ssize_t     w;
516   const char *buf;
517 
518   buf = vbuf;
519   n   = len;
520   while (n > 0) {
521     if ((w = write( sock, buf, n)) <= 0) {
522       if (errno == EINTR) {
523         w = 0;
524       } else {
525         return -1;
526       }
527     }
528     n   -= w;
529     buf += w;
530   }
531   return len;
532 }
533 
534 /**
535  * local function
536  * returns ssize_t
537  * writes vbuf to sock
538  */
539 #ifdef  HAVE_SSL
540 private ssize_t
__ssl_socket_write(CONN * C,const void * vbuf,size_t len)541 __ssl_socket_write(CONN *C, const void *vbuf, size_t len)
542 {
543   size_t      n;
544   ssize_t     w;
545   const char *buf;
546   int         err;
547 
548   buf = vbuf;
549   n   = len;
550 
551   while (n > 0) {
552     if ((w = SSL_write(C->ssl, buf, n)) <= 0) {
553       if (w < 0) {
554         err = SSL_get_error(C->ssl, w);
555 
556         switch (err) {
557           case SSL_ERROR_WANT_READ:
558           case SSL_ERROR_WANT_WRITE:
559 			NOTIFY(DEBUG, "SSL_write non-critical error %d", err);
560           return 0;
561         case SSL_ERROR_SYSCALL:
562           NOTIFY(ERROR, "SSL_write() failed (syscall)");
563           return -1;
564         case SSL_ERROR_SSL:
565           return -1;
566         }
567       }
568       NOTIFY(ERROR, "SSL_write() failed.");
569       return -1;
570     }
571     n   -= w;
572     buf += w;
573   }
574   return len;
575 }
576 #endif/*HAVE_SSL*/
577 
578 ssize_t
socket_read(CONN * C,void * vbuf,size_t len)579 socket_read(CONN *C, void *vbuf, size_t len)
580 {
581   int type;
582   size_t      n;
583   ssize_t     r;
584   char *buf;
585   int ret_eof = 0;
586 
587   pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &type);
588 
589   buf = vbuf;
590   n   = len;
591   if (C->encrypt == TRUE) {
592   #ifdef HAVE_SSL
593     while (n > 0) {
594       if (__socket_check(C, READ) == FALSE) {
595         NOTIFY(WARNING, "socket: read check timed out(%d) %s:%d", (my.timeout)?my.timeout:15, __FILE__, __LINE__);
596 	return -1;
597       }
598 	  r = SSL_read(C->ssl, buf, n);
599       if (r < 0) {
600         if (errno == EINTR || SSL_get_error(C->ssl, r) == SSL_ERROR_WANT_READ)
601           r = 0;
602         else
603           return -1;
604       }
605       else if (r == 0) break;
606       n   -= r;
607       buf += r;
608     }   /* end of while    */
609   #endif/*HAVE_SSL*/
610   } else {
611     while (n > 0) {
612       if (C->inbuffer < len) {
613         if (__socket_check(C, READ) == FALSE) {
614           NOTIFY(WARNING, "socket: read check timed out(%d) %s:%d", (my.timeout)?my.timeout:15, __FILE__, __LINE__);
615           return -1;
616         }
617       }
618       if (C->inbuffer <  n) {
619         int lidos;
620         memmove(C->buffer,&C->buffer[C->pos_ini],C->inbuffer);
621         C->pos_ini = 0;
622 	if (__socket_check(C, READ) == FALSE) {
623           NOTIFY(WARNING, "socket: read check timed out(%d) %s:%d", (my.timeout)?my.timeout:15, __FILE__, __LINE__);
624 	  return -1;
625 	}
626         lidos = read(C->sock, &C->buffer[C->inbuffer], sizeof(C->buffer)-C->inbuffer);
627         if (lidos == 0)
628           ret_eof = 1;
629         if (lidos < 0) {
630           if (errno==EINTR || errno==EAGAIN)
631             lidos = 0;
632           if (errno==EPIPE){
633             return 0;
634           } else {
635             NOTIFY(ERROR, "socket: read error %s %s:%d", strerror(errno), __FILE__, __LINE__);
636             return 0; /* was return -1 */
637           }
638         }
639         C->inbuffer += lidos;
640       }
641       if (C->inbuffer >= n) {
642         r = n;
643       } else {
644         r = C->inbuffer;
645       }
646       if (r == 0) break;
647       memmove(buf,&C->buffer[C->pos_ini],r);
648       C->pos_ini  += r;
649       C->inbuffer -= r;
650       n   -= r;
651       buf += r;
652       if (ret_eof) break;
653     } /* end of while */
654   }   /* end of else  */
655 
656   pthread_setcanceltype(type,NULL);
657   pthread_testcancel();
658   return (len - n);
659 }
660 /**
661  * this function is used for chunked
662  * encoding transfers to acquire the
663  * size of the message check.
664  */
665 ssize_t
socket_readline(CONN * C,char * ptr,size_t maxlen)666 socket_readline(CONN *C, char *ptr, size_t maxlen)
667 {
668   int type;
669   int n, len, res;
670   char c;
671 
672   len = maxlen;
673   pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &type);
674 
675   for (n = 1; n < len; n ++) {
676     if ((res = socket_read(C, &c, 1)) == 1) {
677       *ptr++ = c;
678       if (c=='\n') break;
679     }
680     else if (res == 0) {
681       if (n == 1)
682         return 0;
683       else
684         break;
685     } else {
686       return -1; /* something bad happened */
687     }
688   } /* end of for loop */
689 
690   *ptr=0;
691 
692   pthread_setcanceltype(type,NULL);
693   pthread_testcancel();
694 
695   return n;
696 }
697 
698 /**
699  * returns void
700  * socket_write wrapper function.
701  */
702 int
socket_write(CONN * C,const void * buf,size_t len)703 socket_write(CONN *C, const void *buf, size_t len)
704 {
705   int     type;
706   size_t bytes;
707 
708   pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &type);
709 
710   if (C->encrypt == TRUE) {
711     /* handle HTTPS protocol */
712     #ifdef HAVE_SSL
713     /**
714      * Yeah, sure, this looks like a potential
715      * endless loop, (see: Loop, endless), but
716      * a socket timeout will break it...
717      */
718     do {
719       if ((bytes = __ssl_socket_write(C, buf, len)) != len) {
720         if (bytes == 0)
721           ;
722         else
723           return -1;
724       }
725     } while (bytes == 0);
726     #else
727     NOTIFY(ERROR, "%s:%d protocol NOT supported", __FILE__, __LINE__);
728     return -1;
729     #endif/*HAVE_SSL*/
730   } else {
731     /* assume HTTP */
732     if ((bytes = __socket_write(C->sock, buf, len)) != len) {
733       NOTIFY(ERROR, "unable to write to socket %s:%d", __FILE__, __LINE__);
734       return -1;
735     }
736   }
737 
738   pthread_setcanceltype(type,NULL);
739   pthread_testcancel();
740 
741   return bytes;
742 }
743 
744 /**
745  * returns void
746  * frees ssl resources if using ssl and
747  * closes the connection and the socket.
748  */
749 void
socket_close(CONN * C)750 socket_close(CONN *C)
751 {
752   int   type;
753   int   ret   = 0;
754 #ifdef  HAVE_SSL
755   int tries = 0;
756 #endif/*HAVE_SSL*/
757   if (C==NULL) return;
758 
759   /* XXX Is this necessary? */
760   pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &type);
761 
762   if (C->encrypt == TRUE) {
763 #ifdef  HAVE_SSL
764     if (!C->connection.reuse || C->connection.max == 1){
765       if (C->ssl != NULL) {
766         do {
767           ret = SSL_get_shutdown(C->ssl);
768           if (ret < 0) {
769             NOTIFY(WARNING, "socket: SSL Socket closed by server: %s:%d", __FILE__, __LINE__);
770             break; //what an asshole; is this IIS?
771           }
772 
773           ret = SSL_shutdown(C->ssl);
774           if (ret == 1) {
775             break;
776           }
777           tries++;
778         } while(tries < 5);
779       }
780       SSL_free(C->ssl);
781       C->ssl = NULL;
782       SSL_CTX_free(C->ctx);
783       C->ctx = NULL;
784       close(C->sock);
785       C->sock              = -1;
786       C->connection.status =  0;
787       C->connection.max    =  0;
788       C->connection.tested =  0;
789     }
790 #endif/*HAVE_SSL*/
791   } else {
792     if (C->connection.reuse == 0 || C->connection.max == 1) {
793       if (C->sock != -1) {
794         if ((__socket_block(C->sock, FALSE)) < 0)
795           NOTIFY(ERROR, "unable to set to non-blocking %s:%d", __FILE__, __LINE__);
796         if ((C->connection.status > 1)&&(ret = shutdown(C->sock, 2)) < 0)
797           NOTIFY(ERROR, "unable to shutdown the socket %s:%d", __FILE__, __LINE__);
798         if ((ret = close(C->sock)) < 0)
799           NOTIFY(ERROR, "unable to close the socket %s:%d",    __FILE__, __LINE__);
800       }
801       C->sock                 = -1;
802       C->connection.status    =  0;
803       C->connection.max       =  0;
804       C->connection.tested    =  0;
805     }
806   }
807   C = NULL;
808   pthread_setcanceltype(type,NULL);
809   pthread_testcancel();
810 
811   return;
812 }
813 
814 
815