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
32static int ShutdownAccept = 0;
33
34void ne_net_shutdown()
35{
36  ShutdownAccept = 1;
37}
38
39/* Server side */
40NEOERR *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
110NEOERR *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 */
149NEOERR *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
282NEOERR *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... */
306static 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
367NEOERR *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... */
412NEOERR *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
442NEOERR *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
485static 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
520NEOERR *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
570NEOERR *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
587NEOERR *ne_net_read_int(NSOCK *sock, int *i)
588{
589  return nerr_pass(_ne_net_read_int(sock, i, ','));
590}
591
592NEOERR *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
625NEOERR *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
636NEOERR *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
658NEOERR *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
669NEOERR *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