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