• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ne_net_shutdown()34 void ne_net_shutdown()
35 {
36   ShutdownAccept = 1;
37 }
38 
39 /* Server side */
ne_net_listen(int port,int * fd)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 
ne_net_accept(NSOCK ** sock,int sfd,int data_timeout)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 */
ne_net_connect(NSOCK ** sock,const char * host,int port,int conn_timeout,int data_timeout)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 
ne_net_close(NSOCK ** sock)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... */
ne_net_fill(NSOCK * sock)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 
ne_net_flush(NSOCK * sock)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... */
ne_net_read(NSOCK * sock,UINT8 * buf,int buflen)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 
ne_net_read_line(NSOCK * sock,char ** buf)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 
_ne_net_read_int(NSOCK * sock,int * i,char end)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 
ne_net_read_binary(NSOCK * sock,UINT8 ** b,int * blen)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 
ne_net_read_str_alloc(NSOCK * sock,char ** s,int * len)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 
ne_net_read_int(NSOCK * sock,int * i)587 NEOERR *ne_net_read_int(NSOCK *sock, int *i)
588 {
589   return nerr_pass(_ne_net_read_int(sock, i, ','));
590 }
591 
ne_net_write(NSOCK * sock,const char * b,int blen)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 
ne_net_write_line(NSOCK * sock,const char * s)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 
ne_net_write_binary(NSOCK * sock,const char * b,int blen)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 
ne_net_write_str(NSOCK * sock,const char * s)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 
ne_net_write_int(NSOCK * sock,int i)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