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