Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright 2001-2004 Brandon Long
      3  * All Rights Reserved.
      4  *
      5  * ClearSilver Templating System
      6  *
      7  * This code is made available under the terms of the ClearSilver License.
      8  * http://www.clearsilver.net/license.hdf
      9  *
     10  */
     11 
     12 #include "cs_config.h"
     13 
     14 #include <unistd.h>
     15 #include <sys/socket.h>
     16 #include <sys/time.h>
     17 #include <sys/types.h>
     18 #include <netinet/in.h>
     19 #include <netinet/tcp.h>
     20 #include <netdb.h>
     21 #include <fcntl.h>
     22 #include <stdlib.h>
     23 #include <stdio.h>
     24 #include <errno.h>
     25 #include <string.h>
     26 
     27 #include "neo_misc.h"
     28 #include "neo_err.h"
     29 #include "neo_net.h"
     30 #include "neo_str.h"
     31 
     32 static int ShutdownAccept = 0;
     33 
     34 void ne_net_shutdown()
     35 {
     36   ShutdownAccept = 1;
     37 }
     38 
     39 /* Server side */
     40 NEOERR *ne_net_listen(int port, int *fd)
     41 {
     42   int sfd = 0;
     43   int on = 1;
     44 /*  int flags; */
     45   struct sockaddr_in serv_addr;
     46 
     47   if ((sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
     48     return nerr_raise_errno(NERR_IO, "Unable to create socket");
     49 
     50   if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
     51 	sizeof(on)) == -1)
     52   {
     53     close(sfd);
     54     return nerr_raise_errno(NERR_IO, "Unable to setsockopt(SO_REUSEADDR)");
     55   }
     56 
     57   if(setsockopt (sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
     58 	sizeof(on)) == -1)
     59   {
     60     close(sfd);
     61     return nerr_raise_errno(NERR_IO, "Unable to setsockopt(SO_KEEPALIVE)");
     62   }
     63 
     64   if(setsockopt (sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&on,
     65 	sizeof(on)) == -1)
     66   {
     67     close(sfd);
     68     return nerr_raise_errno(NERR_IO, "Unable to setsockopt(TCP_NODELAY)");
     69   }
     70   serv_addr.sin_family = AF_INET;
     71   serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
     72   serv_addr.sin_port = htons(port);
     73 
     74   if (bind(sfd,(struct sockaddr *)&(serv_addr),sizeof(struct sockaddr)) == -1)
     75   {
     76     close(sfd);
     77     return nerr_raise_errno(NERR_IO, "Unable to bind to port %d", port);
     78   }
     79 
     80   /* If set non-block, then we have to use select prior to accept...
     81    * typically we don't, so we'll leave this out until we have a need
     82    * for it and then figure out how to work it into the common code */
     83   /*
     84   flags = fcntl(sfd, F_GETFL, 0 );
     85   if (flags == -1)
     86   {
     87     close(sfd);
     88     return nerr_raise_errno(NERR_IO, "Unable to get socket flags for port %d",
     89 	port);
     90   }
     91 
     92   if (fcntl(sfd, F_SETFL, flags | O_NDELAY) == -1)
     93   {
     94     close(sfd);
     95     return nerr_raise_errno(NERR_IO, "Unable to set O_NDELAY for port %d",
     96 	port);
     97   }
     98   */
     99 
    100   if (listen(sfd, 100) == -1)
    101   {
    102     close(sfd);
    103     return nerr_raise_errno(NERR_IO, "Unable to listen on port %d", port);
    104   }
    105   *fd = sfd;
    106 
    107   return STATUS_OK;
    108 }
    109 
    110 NEOERR *ne_net_accept(NSOCK **sock, int sfd, int data_timeout)
    111 {
    112   NSOCK *my_sock;
    113   int fd;
    114   struct sockaddr_in client_addr;
    115   socklen_t len;
    116 
    117   len = sizeof(struct sockaddr_in);
    118   while (1)
    119   {
    120     fd = accept(sfd, (struct sockaddr *)&client_addr, &len);
    121     if (fd >= 0) break;
    122     if (ShutdownAccept || errno != EINTR)
    123     {
    124       return nerr_raise_errno(NERR_IO, "accept() returned error");
    125     }
    126     if (errno == EINTR)
    127     {
    128       ne_warn("accept received EINTR");
    129     }
    130   }
    131 
    132   my_sock = (NSOCK *) calloc(1, sizeof(NSOCK));
    133   if (my_sock == NULL)
    134   {
    135     close(fd);
    136     return nerr_raise(NERR_NOMEM, "Unable to allocate memory for NSOCK");
    137   }
    138   my_sock->fd = fd;
    139   my_sock->remote_ip = ntohl(client_addr.sin_addr.s_addr);
    140   my_sock->remote_port = ntohs(client_addr.sin_port);
    141   my_sock->data_timeout = data_timeout;
    142 
    143   *sock = my_sock;
    144 
    145   return STATUS_OK;
    146 }
    147 
    148 /* Client side */
    149 NEOERR *ne_net_connect(NSOCK **sock, const char *host, int port,
    150                        int conn_timeout, int data_timeout)
    151 {
    152   struct sockaddr_in serv_addr;
    153   struct hostent hp;
    154   struct hostent *php;
    155   int fd;
    156   int r = 0, x;
    157   int flags;
    158   struct timeval tv;
    159   fd_set fds;
    160   int optval;
    161   socklen_t optlen;
    162   NSOCK *my_sock;
    163 
    164   /* FIXME: This isn't thread safe... but there's no man entry for the _r
    165    * version? */
    166 
    167   php = gethostbyname(host);
    168   if (php == NULL)
    169   {
    170     return nerr_raise(NERR_IO, "Host not found: %s", hstrerror(h_errno));
    171   }
    172   hp = *php;
    173 
    174   memset(&serv_addr, 0, sizeof(serv_addr));
    175   serv_addr.sin_family = AF_INET;
    176   serv_addr.sin_port = htons(port);
    177   fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    178   if (fd == -1)
    179     return nerr_raise_errno(NERR_IO, "Unable to create socket");
    180 
    181   flags = fcntl(fd, F_GETFL, 0 );
    182   if (flags == -1)
    183   {
    184     close(fd);
    185     return nerr_raise_errno(NERR_IO, "Unable to get socket flags");
    186   }
    187 
    188   if (fcntl(fd, F_SETFL, flags | O_NDELAY) == -1)
    189   {
    190     close(fd);
    191     return nerr_raise_errno(NERR_IO, "Unable to set O_NDELAY");
    192   }
    193 
    194   x = 0;
    195   while (hp.h_addr_list[x] != NULL)
    196   {
    197     memcpy(&(serv_addr.sin_addr), hp.h_addr_list[x], sizeof(struct in_addr));
    198     errno = 0;
    199     r = connect(fd, (struct sockaddr *) &(serv_addr), sizeof(struct sockaddr_in));
    200     if (r == 0 || errno == EINPROGRESS) break;
    201     x++;
    202   }
    203   if (r != 0)
    204   {
    205     if (errno != EINPROGRESS)
    206     {
    207       close(fd);
    208       return nerr_raise_errno(NERR_IO, "Unable to connect to %s:%d",
    209 	  host, port);
    210     }
    211     tv.tv_sec = conn_timeout;
    212     tv.tv_usec = 0;
    213 
    214     FD_ZERO(&fds);
    215     FD_SET(fd, &fds);
    216 
    217     r = select(fd+1, NULL, &fds, NULL, &tv);
    218     if (r == 0)
    219     {
    220       close(fd);
    221       return nerr_raise(NERR_IO, "Connection to %s:%d failed: Timeout", host,
    222 	  port);
    223     }
    224     if (r < 0)
    225     {
    226       close(fd);
    227       return nerr_raise_errno(NERR_IO, "Connection to %s:%d failed", host,
    228 	  port);
    229     }
    230 
    231     optlen = sizeof(optval);
    232 
    233     if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1)
    234     {
    235       close(fd);
    236       return nerr_raise_errno(NERR_IO,
    237 	  "Unable to getsockopt to determine connection error");
    238     }
    239 
    240     if (optval)
    241     {
    242       close(fd);
    243       errno = optval;
    244       return nerr_raise_errno(NERR_IO, "Connection to %s:%d failed", host,
    245 	  port);
    246     }
    247   }
    248   /* Re-enable blocking... we'll use select on read/write for timeouts
    249    * anyways, and if we want non-blocking version in the future we'll
    250    * add a flag or something.
    251    */
    252   flags = fcntl(fd, F_GETFL, 0 );
    253   if (flags == -1)
    254   {
    255     close(fd);
    256     return nerr_raise_errno(NERR_IO, "Unable to get socket flags");
    257   }
    258 
    259   if (fcntl(fd, F_SETFL, flags & ~O_NDELAY) == -1)
    260   {
    261     close(fd);
    262     return nerr_raise_errno(NERR_IO, "Unable to set O_NDELAY");
    263   }
    264 
    265   my_sock = (NSOCK *) calloc(1, sizeof(NSOCK));
    266   if (my_sock == NULL)
    267   {
    268     close(fd);
    269     return nerr_raise(NERR_NOMEM, "Unable to allocate memory for NSOCK");
    270   }
    271   my_sock->fd = fd;
    272   my_sock->remote_ip = ntohl(serv_addr.sin_addr.s_addr);
    273   my_sock->remote_port = port;
    274   my_sock->data_timeout = data_timeout;
    275   my_sock->conn_timeout = conn_timeout;
    276 
    277   *sock = my_sock;
    278 
    279   return STATUS_OK;
    280 }
    281 
    282 NEOERR *ne_net_close(NSOCK **sock)
    283 {
    284   NEOERR *err;
    285 
    286   if (sock == NULL || *sock == NULL) return STATUS_OK;
    287   err = ne_net_flush(*sock);
    288   close((*sock)->fd);
    289   free((*sock));
    290   *sock = NULL;
    291   return nerr_pass(err);
    292 }
    293 
    294 /* Low level data interface ... we are implementing a buffered stream
    295  * here, and the fill and flush are designed for that.  More over, our
    296  * buffered stream assumes a certain type of protocol design where we
    297  * flush the write buffer before reading... there are possible protocols
    298  * where this would be grossly inefficient, but I don't expect to use
    299  * anything like that */
    300 
    301 /* Also, an annoyance here... what to do with the EOF case?  Currently,
    302  * we're just returing with a ol of 0, which means in most cases when
    303  * calling this we have to check that case as well as standard errors.
    304  * We could raise an NERR_EOF or something, but that seems like
    305  * overkill.  We should probably have a ret arg for the case... */
    306 static NEOERR *ne_net_fill(NSOCK *sock)
    307 {
    308   NEOERR *err;
    309   struct timeval tv;
    310   fd_set fds;
    311   int r;
    312 
    313   /* Ok, we are assuming a model where one side of the connection is the
    314    * consumer and the other the producer... and then it switches.  So we
    315    * flush the output buffer (if any) before we read */
    316   if (sock->ol)
    317   {
    318     err = ne_net_flush(sock);
    319     if (err) return nerr_pass(err);
    320   }
    321 
    322   /* Ok, we want connections to fail if they don't connect in
    323    * conn_timeout... but with higher listen queues, the connection could
    324    * actually connect, but the remote server won't get to it within the
    325    * conn_timeout, we still want it to fail.  We do that by using the
    326    * conn_timeout on the first read ... this isn't quite the same as we
    327    * might actually timeout at almost 2x conn_timeout (if we had to wait
    328    * for connect and the first read) but its still better then waiting
    329    * the full data timeout */
    330   if (sock->conn_timeout)
    331   {
    332     tv.tv_sec = sock->conn_timeout;
    333     sock->conn_timeout = 0;
    334   }
    335   else
    336   {
    337     tv.tv_sec = sock->data_timeout;
    338   }
    339   tv.tv_usec = 0;
    340 
    341   FD_ZERO(&fds);
    342   FD_SET(sock->fd, &fds);
    343 
    344   r = select(sock->fd+1, &fds, NULL, NULL, &tv);
    345   if (r == 0)
    346   {
    347     return nerr_raise(NERR_IO, "read failed: Timeout");
    348   }
    349   if (r < 0)
    350   {
    351     return nerr_raise_errno(NERR_IO, "select for read failed");
    352   }
    353 
    354   sock->ibuf[0] = '\0';
    355   r = read(sock->fd, sock->ibuf, NET_BUFSIZE);
    356   if (r < 0)
    357   {
    358     return nerr_raise_errno(NERR_IO, "read failed");
    359   }
    360 
    361   sock->ib = 0;
    362   sock->il = r;
    363 
    364   return STATUS_OK;
    365 }
    366 
    367 NEOERR *ne_net_flush(NSOCK *sock)
    368 {
    369   fd_set fds;
    370   struct timeval tv;
    371   int r;
    372   int x = 0;
    373 
    374   if (sock->conn_timeout)
    375   {
    376     tv.tv_sec = sock->conn_timeout;
    377   }
    378   else
    379   {
    380     tv.tv_sec = sock->data_timeout;
    381   }
    382   tv.tv_usec = 0;
    383 
    384   x = 0;
    385   while (x < sock->ol)
    386   {
    387     FD_ZERO(&fds);
    388     FD_SET(sock->fd, &fds);
    389 
    390     r = select(sock->fd+1, NULL, &fds, NULL, &tv);
    391     if (r == 0)
    392     {
    393       return nerr_raise(NERR_IO, "write failed: Timeout");
    394     }
    395     if (r < 0)
    396     {
    397       return nerr_raise_errno(NERR_IO, "select for write failed");
    398     }
    399 
    400     r = write(sock->fd, sock->obuf + x, sock->ol - x);
    401     if (r < 0)
    402     {
    403       return nerr_raise_errno(NERR_IO, "select for write failed");
    404     }
    405     x += r;
    406   }
    407   sock->ol = 0;
    408   return STATUS_OK;
    409 }
    410 
    411 /* hmm, we may need something to know how much we've read here... */
    412 NEOERR *ne_net_read(NSOCK *sock, UINT8 *buf, int buflen)
    413 {
    414   NEOERR *err;
    415   int x = 0;
    416   int l;
    417 
    418   x = buflen;
    419   while (x > 0)
    420   {
    421     if (sock->il - sock->ib > 0)
    422     {
    423       if (sock->ib + x <= sock->il)
    424 	l = x;
    425       else
    426 	l = sock->il - sock->ib;
    427 
    428       memcpy(buf + buflen - x, sock->ibuf + sock->ib, l);
    429       sock->ib += l;
    430       x -= l;
    431     }
    432     else
    433     {
    434       err = ne_net_fill(sock);
    435       if (err) return nerr_pass(err);
    436       if (sock->il == 0) return STATUS_OK;
    437     }
    438   }
    439   return STATUS_OK;
    440 }
    441 
    442 NEOERR *ne_net_read_line(NSOCK *sock, char **buf)
    443 {
    444   NEOERR *err;
    445   STRING str;
    446   UINT8 *nl;
    447   int l;
    448 
    449   string_init(&str);
    450 
    451   while (1)
    452   {
    453     if (sock->il - sock->ib > 0)
    454     {
    455       nl = memchr(sock->ibuf + sock->ib, '\n', sock->il - sock->ib);
    456       if (nl == NULL)
    457       {
    458 	l = sock->il - sock->ib;
    459 	err = string_appendn(&str, (char *)(sock->ibuf + sock->ib), l);
    460 	sock->ib += l;
    461 	if (err) break;
    462       }
    463       else
    464       {
    465 	l = nl - (sock->ibuf + sock->ib);
    466 	err = string_appendn(&str, (char *)(sock->ibuf + sock->ib), l);
    467 	sock->ib += l;
    468 	if (err) break;
    469 
    470 	*buf = str.buf;
    471 	return STATUS_OK;
    472       }
    473     }
    474     else
    475     {
    476       err = ne_net_fill(sock);
    477       if (err) break;
    478       if (sock->il == 0) return STATUS_OK;
    479     }
    480   }
    481   string_clear(&str);
    482   return nerr_pass(err);
    483 }
    484 
    485 static NEOERR *_ne_net_read_int(NSOCK *sock, int *i, char end)
    486 {
    487   NEOERR *err;
    488   int x = 0;
    489   char buf[32];
    490   char *ep = NULL;
    491 
    492   while (x < sizeof(buf))
    493   {
    494     while (sock->il - sock->ib > 0)
    495     {
    496       buf[x] = sock->ibuf[sock->ib++];
    497       if (buf[x] == end) break;
    498       x++;
    499       if (x == sizeof(buf)) break;
    500     }
    501     if (buf[x] == end) break;
    502     err = ne_net_fill(sock);
    503     if (err) return nerr_pass(err);
    504     if (sock->il == 0) return STATUS_OK;
    505   }
    506 
    507   if (x == sizeof(buf))
    508     return nerr_raise(NERR_PARSE, "Format error on stream, expected '%c'", end);
    509 
    510   buf[x] = '\0';
    511   *i = strtol(buf, &ep, 10);
    512   if (ep && *ep)
    513   {
    514     return nerr_raise(NERR_PARSE, "Format error on stream, expected number followed by '%c'", end);
    515   }
    516 
    517   return STATUS_OK;
    518 }
    519 
    520 NEOERR *ne_net_read_binary(NSOCK *sock, UINT8 **b, int *blen)
    521 {
    522   NEOERR *err;
    523   UINT8 *data;
    524   UINT8 buf[5];
    525   int l;
    526 
    527   err = _ne_net_read_int(sock, &l, ':');
    528   if (err) return nerr_pass(err);
    529 
    530   /* Special case to read a NULL */
    531   if (l < 0)
    532   {
    533     *b = NULL;
    534     if (blen != NULL) *blen = l;
    535     return STATUS_OK;
    536   }
    537 
    538   data = (UINT8 *) malloc(l + 1);
    539   if (data == NULL)
    540   {
    541     /* We might want to clear the incoming data here... */
    542     return nerr_raise(NERR_NOMEM,
    543 	"Unable to allocate memory for binary data %d" , l);
    544   }
    545 
    546   err = ne_net_read(sock, data, l);
    547   if (err)
    548   {
    549     free(data);
    550     return nerr_pass(err);
    551   }
    552   /* check for comma separator */
    553   err = ne_net_read(sock, buf, 1);
    554   if (err)
    555   {
    556     free(data);
    557     return nerr_pass(err);
    558   }
    559   if (buf[0] != ',')
    560   {
    561     free(data);
    562     return nerr_raise(NERR_PARSE, "Format error on stream, expected ','");
    563   }
    564 
    565   *b = data;
    566   if (blen != NULL) *blen = l;
    567   return STATUS_OK;
    568 }
    569 
    570 NEOERR *ne_net_read_str_alloc(NSOCK *sock, char **s, int *len)
    571 {
    572   NEOERR *err;
    573   int l;
    574 
    575   /* just use the binary read and null terminate the string... */
    576   err = ne_net_read_binary(sock, (UINT8 **)s, &l);
    577   if (err) return nerr_pass(err);
    578 
    579   if (*s != NULL)
    580   {
    581     (*s)[l] = '\0';
    582   }
    583   if (len != NULL) *len = l;
    584   return STATUS_OK;
    585 }
    586 
    587 NEOERR *ne_net_read_int(NSOCK *sock, int *i)
    588 {
    589   return nerr_pass(_ne_net_read_int(sock, i, ','));
    590 }
    591 
    592 NEOERR *ne_net_write(NSOCK *sock, const char *b, int blen)
    593 {
    594   NEOERR *err;
    595   int x = 0;
    596   int l;
    597 
    598   x = blen;
    599   while (x > 0)
    600   {
    601     if (sock->ol < NET_BUFSIZE)
    602     {
    603       if (sock->ol + x <= NET_BUFSIZE)
    604       {
    605 	l = x;
    606       }
    607       else
    608       {
    609 	l = NET_BUFSIZE - sock->ol;
    610       }
    611 
    612       memcpy(sock->obuf + sock->ol, b + blen - x, l);
    613       sock->ol += l;
    614       x -= l;
    615     }
    616     else
    617     {
    618       err = ne_net_flush(sock);
    619       if (err) return nerr_pass(err);
    620     }
    621   }
    622   return STATUS_OK;
    623 }
    624 
    625 NEOERR *ne_net_write_line(NSOCK *sock, const char *s)
    626 {
    627   NEOERR *err;
    628 
    629   err = ne_net_write(sock, s, strlen(s));
    630   if (err) return nerr_pass(err);
    631   err = ne_net_write(sock, "\n", 1);
    632   if (err) return nerr_pass(err);
    633   return STATUS_OK;
    634 }
    635 
    636 NEOERR *ne_net_write_binary(NSOCK *sock, const char *b, int blen)
    637 {
    638   NEOERR *err;
    639   char buf[32];
    640 
    641   if (b == NULL) blen = -1;
    642 
    643   snprintf(buf, sizeof(buf), "%d:", blen);
    644   err = ne_net_write(sock, buf, strlen(buf));
    645   if (err) return nerr_pass(err);
    646 
    647   if (blen > 0)
    648   {
    649     err = ne_net_write(sock, b, blen);
    650     if (err) return nerr_pass(err);
    651   }
    652 
    653   err = ne_net_write(sock, ",", 1);
    654   if (err) return nerr_pass(err);
    655   return STATUS_OK;
    656 }
    657 
    658 NEOERR *ne_net_write_str(NSOCK *sock, const char *s)
    659 {
    660   NEOERR *err;
    661 
    662   if (s == NULL)
    663     err = ne_net_write_binary(sock, s, -1);
    664   else
    665     err = ne_net_write_binary(sock, s, strlen(s));
    666   return nerr_pass(err);
    667 }
    668 
    669 NEOERR *ne_net_write_int(NSOCK *sock, int i)
    670 {
    671   char buf[32];
    672 
    673   snprintf(buf, sizeof(buf), "%d,", i);
    674   return nerr_pass(ne_net_write(sock, buf, strlen(buf)));
    675 }
    676 
    677