1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 #include "server_setup.h" 23 24 /* sws.c: simple (silly?) web server 25 26 This code was originally graciously donated to the project by Juergen 27 Wilke. Thanks a bunch! 28 29 */ 30 31 #ifdef HAVE_SIGNAL_H 32 #include <signal.h> 33 #endif 34 #ifdef HAVE_NETINET_IN_H 35 #include <netinet/in.h> 36 #endif 37 #ifdef HAVE_NETINET_IN6_H 38 #include <netinet/in6.h> 39 #endif 40 #ifdef HAVE_ARPA_INET_H 41 #include <arpa/inet.h> 42 #endif 43 #ifdef HAVE_NETDB_H 44 #include <netdb.h> 45 #endif 46 #ifdef HAVE_NETINET_TCP_H 47 #include <netinet/tcp.h> /* for TCP_NODELAY */ 48 #endif 49 50 #define ENABLE_CURLX_PRINTF 51 /* make the curlx header define all printf() functions to use the curlx_* 52 versions instead */ 53 #include "curlx.h" /* from the private lib dir */ 54 #include "getpart.h" 55 #include "inet_pton.h" 56 #include "util.h" 57 #include "server_sockaddr.h" 58 59 /* include memdebug.h last */ 60 #include "memdebug.h" 61 62 #ifdef USE_WINSOCK 63 #undef EINTR 64 #define EINTR 4 /* errno.h value */ 65 #undef EAGAIN 66 #define EAGAIN 11 /* errno.h value */ 67 #undef ERANGE 68 #define ERANGE 34 /* errno.h value */ 69 #endif 70 71 static enum { 72 socket_domain_inet = AF_INET 73 #ifdef ENABLE_IPV6 74 , socket_domain_inet6 = AF_INET6 75 #endif 76 #ifdef USE_UNIX_SOCKETS 77 , socket_domain_unix = AF_UNIX 78 #endif 79 } socket_domain = AF_INET; 80 static bool use_gopher = FALSE; 81 static int serverlogslocked = 0; 82 static bool is_proxy = FALSE; 83 84 #define REQBUFSIZ 150000 85 #define REQBUFSIZ_TXT "149999" 86 87 static long prevtestno = -1; /* previous test number we served */ 88 static long prevpartno = -1; /* previous part number we served */ 89 static bool prevbounce = FALSE; /* instructs the server to increase the part 90 number for a test in case the identical 91 testno+partno request shows up again */ 92 93 #define RCMD_NORMALREQ 0 /* default request, use the tests file normally */ 94 #define RCMD_IDLE 1 /* told to sit idle */ 95 #define RCMD_STREAM 2 /* told to stream */ 96 97 struct httprequest { 98 char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */ 99 bool connect_request; /* if a CONNECT */ 100 unsigned short connect_port; /* the port number CONNECT used */ 101 size_t checkindex; /* where to start checking of the request */ 102 size_t offset; /* size of the incoming request */ 103 long testno; /* test number found in the request */ 104 long partno; /* part number found in the request */ 105 bool open; /* keep connection open info, as found in the request */ 106 bool auth_req; /* authentication required, don't wait for body unless 107 there's an Authorization header */ 108 bool auth; /* Authorization header present in the incoming request */ 109 size_t cl; /* Content-Length of the incoming request */ 110 bool digest; /* Authorization digest header found */ 111 bool ntlm; /* Authorization ntlm header found */ 112 int writedelay; /* if non-zero, delay this number of seconds between 113 writes in the response */ 114 int pipe; /* if non-zero, expect this many requests to do a "piped" 115 request/response */ 116 int skip; /* if non-zero, the server is instructed to not read this 117 many bytes from a PUT/POST request. Ie the client sends N 118 bytes said in Content-Length, but the server only reads N 119 - skip bytes. */ 120 int rcmd; /* doing a special command, see defines above */ 121 int prot_version; /* HTTP version * 10 */ 122 bool pipelining; /* true if request is pipelined */ 123 int callcount; /* times ProcessRequest() gets called */ 124 bool connmon; /* monitor the state of the connection, log disconnects */ 125 bool upgrade; /* test case allows upgrade to http2 */ 126 bool upgrade_request; /* upgrade request found and allowed */ 127 int done_processing; 128 }; 129 130 #define MAX_SOCKETS 1024 131 132 static curl_socket_t all_sockets[MAX_SOCKETS]; 133 static size_t num_sockets = 0; 134 135 static int ProcessRequest(struct httprequest *req); 136 static void storerequest(const char *reqbuf, size_t totalsize); 137 138 #define DEFAULT_PORT 8999 139 140 #ifndef DEFAULT_LOGFILE 141 #define DEFAULT_LOGFILE "log/sws.log" 142 #endif 143 144 const char *serverlogfile = DEFAULT_LOGFILE; 145 146 #define SWSVERSION "curl test suite HTTP server/0.1" 147 148 #define REQUEST_DUMP "log/server.input" 149 #define RESPONSE_DUMP "log/server.response" 150 151 /* when told to run as proxy, we store the logs in different files so that 152 they can co-exist with the same program running as a "server" */ 153 #define REQUEST_PROXY_DUMP "log/proxy.input" 154 #define RESPONSE_PROXY_DUMP "log/proxy.response" 155 156 /* very-big-path support */ 157 #define MAXDOCNAMELEN 140000 158 #define MAXDOCNAMELEN_TXT "139999" 159 160 #define REQUEST_KEYWORD_SIZE 256 161 #define REQUEST_KEYWORD_SIZE_TXT "255" 162 163 #define CMD_AUTH_REQUIRED "auth_required" 164 165 /* 'idle' means that it will accept the request fine but never respond 166 any data. Just keep the connection alive. */ 167 #define CMD_IDLE "idle" 168 169 /* 'stream' means to send a never-ending stream of data */ 170 #define CMD_STREAM "stream" 171 172 /* 'connection-monitor' will output when a server/proxy connection gets 173 disconnected as for some cases it is important that it gets done at the 174 proper point - like with NTLM */ 175 #define CMD_CONNECTIONMONITOR "connection-monitor" 176 177 /* upgrade to http2 */ 178 #define CMD_UPGRADE "upgrade" 179 180 #define END_OF_HEADERS "\r\n\r\n" 181 182 enum { 183 DOCNUMBER_NOTHING = -4, 184 DOCNUMBER_QUIT = -3, 185 DOCNUMBER_WERULEZ = -2, 186 DOCNUMBER_404 = -1 187 }; 188 189 static const char *end_of_headers = END_OF_HEADERS; 190 191 /* sent as reply to a QUIT */ 192 static const char *docquit = 193 "HTTP/1.1 200 Goodbye" END_OF_HEADERS; 194 195 /* send back this on 404 file not found */ 196 static const char *doc404 = "HTTP/1.1 404 Not Found\r\n" 197 "Server: " SWSVERSION "\r\n" 198 "Connection: close\r\n" 199 "Content-Type: text/html" 200 END_OF_HEADERS 201 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" 202 "<HTML><HEAD>\n" 203 "<TITLE>404 Not Found</TITLE>\n" 204 "</HEAD><BODY>\n" 205 "<H1>Not Found</H1>\n" 206 "The requested URL was not found on this server.\n" 207 "<P><HR><ADDRESS>" SWSVERSION "</ADDRESS>\n" "</BODY></HTML>\n"; 208 209 /* do-nothing macro replacement for systems which lack siginterrupt() */ 210 211 #ifndef HAVE_SIGINTERRUPT 212 #define siginterrupt(x,y) do {} while(0) 213 #endif 214 215 /* vars used to keep around previous signal handlers */ 216 217 typedef RETSIGTYPE (*SIGHANDLER_T)(int); 218 219 #ifdef SIGHUP 220 static SIGHANDLER_T old_sighup_handler = SIG_ERR; 221 #endif 222 223 #ifdef SIGPIPE 224 static SIGHANDLER_T old_sigpipe_handler = SIG_ERR; 225 #endif 226 227 #ifdef SIGALRM 228 static SIGHANDLER_T old_sigalrm_handler = SIG_ERR; 229 #endif 230 231 #ifdef SIGINT 232 static SIGHANDLER_T old_sigint_handler = SIG_ERR; 233 #endif 234 235 #ifdef SIGTERM 236 static SIGHANDLER_T old_sigterm_handler = SIG_ERR; 237 #endif 238 239 #if defined(SIGBREAK) && defined(WIN32) 240 static SIGHANDLER_T old_sigbreak_handler = SIG_ERR; 241 #endif 242 243 /* var which if set indicates that the program should finish execution */ 244 245 SIG_ATOMIC_T got_exit_signal = 0; 246 247 /* if next is set indicates the first signal handled in exit_signal_handler */ 248 249 static volatile int exit_signal = 0; 250 251 /* signal handler that will be triggered to indicate that the program 252 should finish its execution in a controlled manner as soon as possible. 253 The first time this is called it will set got_exit_signal to one and 254 store in exit_signal the signal that triggered its execution. */ 255 256 static RETSIGTYPE exit_signal_handler(int signum) 257 { 258 int old_errno = errno; 259 if(got_exit_signal == 0) { 260 got_exit_signal = 1; 261 exit_signal = signum; 262 } 263 (void)signal(signum, exit_signal_handler); 264 errno = old_errno; 265 } 266 267 static void install_signal_handlers(void) 268 { 269 #ifdef SIGHUP 270 /* ignore SIGHUP signal */ 271 old_sighup_handler = signal(SIGHUP, SIG_IGN); 272 if(old_sighup_handler == SIG_ERR) 273 logmsg("cannot install SIGHUP handler: %s", strerror(errno)); 274 #endif 275 #ifdef SIGPIPE 276 /* ignore SIGPIPE signal */ 277 old_sigpipe_handler = signal(SIGPIPE, SIG_IGN); 278 if(old_sigpipe_handler == SIG_ERR) 279 logmsg("cannot install SIGPIPE handler: %s", strerror(errno)); 280 #endif 281 #ifdef SIGALRM 282 /* ignore SIGALRM signal */ 283 old_sigalrm_handler = signal(SIGALRM, SIG_IGN); 284 if(old_sigalrm_handler == SIG_ERR) 285 logmsg("cannot install SIGALRM handler: %s", strerror(errno)); 286 #endif 287 #ifdef SIGINT 288 /* handle SIGINT signal with our exit_signal_handler */ 289 old_sigint_handler = signal(SIGINT, exit_signal_handler); 290 if(old_sigint_handler == SIG_ERR) 291 logmsg("cannot install SIGINT handler: %s", strerror(errno)); 292 else 293 siginterrupt(SIGINT, 1); 294 #endif 295 #ifdef SIGTERM 296 /* handle SIGTERM signal with our exit_signal_handler */ 297 old_sigterm_handler = signal(SIGTERM, exit_signal_handler); 298 if(old_sigterm_handler == SIG_ERR) 299 logmsg("cannot install SIGTERM handler: %s", strerror(errno)); 300 else 301 siginterrupt(SIGTERM, 1); 302 #endif 303 #if defined(SIGBREAK) && defined(WIN32) 304 /* handle SIGBREAK signal with our exit_signal_handler */ 305 old_sigbreak_handler = signal(SIGBREAK, exit_signal_handler); 306 if(old_sigbreak_handler == SIG_ERR) 307 logmsg("cannot install SIGBREAK handler: %s", strerror(errno)); 308 else 309 siginterrupt(SIGBREAK, 1); 310 #endif 311 } 312 313 static void restore_signal_handlers(void) 314 { 315 #ifdef SIGHUP 316 if(SIG_ERR != old_sighup_handler) 317 (void)signal(SIGHUP, old_sighup_handler); 318 #endif 319 #ifdef SIGPIPE 320 if(SIG_ERR != old_sigpipe_handler) 321 (void)signal(SIGPIPE, old_sigpipe_handler); 322 #endif 323 #ifdef SIGALRM 324 if(SIG_ERR != old_sigalrm_handler) 325 (void)signal(SIGALRM, old_sigalrm_handler); 326 #endif 327 #ifdef SIGINT 328 if(SIG_ERR != old_sigint_handler) 329 (void)signal(SIGINT, old_sigint_handler); 330 #endif 331 #ifdef SIGTERM 332 if(SIG_ERR != old_sigterm_handler) 333 (void)signal(SIGTERM, old_sigterm_handler); 334 #endif 335 #if defined(SIGBREAK) && defined(WIN32) 336 if(SIG_ERR != old_sigbreak_handler) 337 (void)signal(SIGBREAK, old_sigbreak_handler); 338 #endif 339 } 340 341 /* returns true if the current socket is an IP one */ 342 static bool socket_domain_is_ip(void) 343 { 344 switch(socket_domain) { 345 case AF_INET: 346 #ifdef ENABLE_IPV6 347 case AF_INET6: 348 #endif 349 return true; 350 default: 351 /* case AF_UNIX: */ 352 return false; 353 } 354 } 355 356 /* based on the testno, parse the correct server commands */ 357 static int parse_servercmd(struct httprequest *req) 358 { 359 FILE *stream; 360 char *filename; 361 int error; 362 363 filename = test2file(req->testno); 364 365 stream = fopen(filename, "rb"); 366 if(!stream) { 367 error = errno; 368 logmsg("fopen() failed with error: %d %s", error, strerror(error)); 369 logmsg(" [1] Error opening file: %s", filename); 370 logmsg(" Couldn't open test file %ld", req->testno); 371 req->open = FALSE; /* closes connection */ 372 return 1; /* done */ 373 } 374 else { 375 char *orgcmd = NULL; 376 char *cmd = NULL; 377 size_t cmdsize = 0; 378 int num = 0; 379 380 /* get the custom server control "commands" */ 381 error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream); 382 fclose(stream); 383 if(error) { 384 logmsg("getpart() failed with error: %d", error); 385 req->open = FALSE; /* closes connection */ 386 return 1; /* done */ 387 } 388 389 req->connmon = FALSE; 390 391 cmd = orgcmd; 392 while(cmd && cmdsize) { 393 char *check; 394 395 if(!strncmp(CMD_AUTH_REQUIRED, cmd, strlen(CMD_AUTH_REQUIRED))) { 396 logmsg("instructed to require authorization header"); 397 req->auth_req = TRUE; 398 } 399 else if(!strncmp(CMD_IDLE, cmd, strlen(CMD_IDLE))) { 400 logmsg("instructed to idle"); 401 req->rcmd = RCMD_IDLE; 402 req->open = TRUE; 403 } 404 else if(!strncmp(CMD_STREAM, cmd, strlen(CMD_STREAM))) { 405 logmsg("instructed to stream"); 406 req->rcmd = RCMD_STREAM; 407 } 408 else if(!strncmp(CMD_CONNECTIONMONITOR, cmd, 409 strlen(CMD_CONNECTIONMONITOR))) { 410 logmsg("enabled connection monitoring"); 411 req->connmon = TRUE; 412 } 413 else if(!strncmp(CMD_UPGRADE, cmd, strlen(CMD_UPGRADE))) { 414 logmsg("enabled upgrade to http2"); 415 req->upgrade = TRUE; 416 } 417 else if(1 == sscanf(cmd, "pipe: %d", &num)) { 418 logmsg("instructed to allow a pipe size of %d", num); 419 if(num < 0) 420 logmsg("negative pipe size ignored"); 421 else if(num > 0) 422 req->pipe = num-1; /* decrease by one since we don't count the 423 first request in this number */ 424 } 425 else if(1 == sscanf(cmd, "skip: %d", &num)) { 426 logmsg("instructed to skip this number of bytes %d", num); 427 req->skip = num; 428 } 429 else if(1 == sscanf(cmd, "writedelay: %d", &num)) { 430 logmsg("instructed to delay %d secs between packets", num); 431 req->writedelay = num; 432 } 433 else { 434 logmsg("Unknown <servercmd> instruction found: %s", cmd); 435 } 436 /* try to deal with CRLF or just LF */ 437 check = strchr(cmd, '\r'); 438 if(!check) 439 check = strchr(cmd, '\n'); 440 441 if(check) { 442 /* get to the letter following the newline */ 443 while((*check == '\r') || (*check == '\n')) 444 check++; 445 446 if(!*check) 447 /* if we reached a zero, get out */ 448 break; 449 cmd = check; 450 } 451 else 452 break; 453 } 454 free(orgcmd); 455 } 456 457 return 0; /* OK! */ 458 } 459 460 static int ProcessRequest(struct httprequest *req) 461 { 462 char *line = &req->reqbuf[req->checkindex]; 463 bool chunked = FALSE; 464 static char request[REQUEST_KEYWORD_SIZE]; 465 static char doc[MAXDOCNAMELEN]; 466 char logbuf[456]; 467 int prot_major, prot_minor; 468 char *end = strstr(line, end_of_headers); 469 470 req->callcount++; 471 472 logmsg("Process %d bytes request%s", req->offset, 473 req->callcount > 1?" [CONTINUED]":""); 474 475 /* try to figure out the request characteristics as soon as possible, but 476 only once! */ 477 478 if(use_gopher && 479 (req->testno == DOCNUMBER_NOTHING) && 480 !strncmp("/verifiedserver", line, 15)) { 481 logmsg("Are-we-friendly question received"); 482 req->testno = DOCNUMBER_WERULEZ; 483 return 1; /* done */ 484 } 485 486 else if((req->testno == DOCNUMBER_NOTHING) && 487 sscanf(line, 488 "%" REQUEST_KEYWORD_SIZE_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", 489 request, 490 doc, 491 &prot_major, 492 &prot_minor) == 4) { 493 char *ptr; 494 495 req->prot_version = prot_major*10 + prot_minor; 496 497 /* find the last slash */ 498 ptr = strrchr(doc, '/'); 499 500 /* get the number after it */ 501 if(ptr) { 502 if((strlen(doc) + strlen(request)) < 400) 503 snprintf(logbuf, sizeof(logbuf), "Got request: %s %s HTTP/%d.%d", 504 request, doc, prot_major, prot_minor); 505 else 506 snprintf(logbuf, sizeof(logbuf), "Got a *HUGE* request HTTP/%d.%d", 507 prot_major, prot_minor); 508 logmsg("%s", logbuf); 509 510 if(!strncmp("/verifiedserver", ptr, 15)) { 511 logmsg("Are-we-friendly question received"); 512 req->testno = DOCNUMBER_WERULEZ; 513 return 1; /* done */ 514 } 515 516 if(!strncmp("/quit", ptr, 5)) { 517 logmsg("Request-to-quit received"); 518 req->testno = DOCNUMBER_QUIT; 519 return 1; /* done */ 520 } 521 522 ptr++; /* skip the slash */ 523 524 /* skip all non-numericals following the slash */ 525 while(*ptr && !ISDIGIT(*ptr)) 526 ptr++; 527 528 req->testno = strtol(ptr, &ptr, 10); 529 530 if(req->testno > 10000) { 531 req->partno = req->testno % 10000; 532 req->testno /= 10000; 533 } 534 else 535 req->partno = 0; 536 537 if(req->testno) { 538 539 snprintf(logbuf, sizeof(logbuf), "Requested test number %ld part %ld", 540 req->testno, req->partno); 541 logmsg("%s", logbuf); 542 543 /* find and parse <servercmd> for this test */ 544 parse_servercmd(req); 545 } 546 else 547 req->testno = DOCNUMBER_NOTHING; 548 549 } 550 551 if(req->testno == DOCNUMBER_NOTHING) { 552 /* didn't find any in the first scan, try alternative test case 553 number placements */ 554 555 if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", 556 doc, &prot_major, &prot_minor) == 3) { 557 char *portp = NULL; 558 unsigned long part = 0; 559 560 snprintf(logbuf, sizeof(logbuf), 561 "Received a CONNECT %s HTTP/%d.%d request", 562 doc, prot_major, prot_minor); 563 logmsg("%s", logbuf); 564 565 req->connect_request = TRUE; 566 567 if(req->prot_version == 10) 568 req->open = FALSE; /* HTTP 1.0 closes connection by default */ 569 570 if(doc[0] == '[') { 571 char *p = &doc[1]; 572 /* scan through the hexgroups and store the value of the last group 573 in the 'part' variable and use as test case number!! */ 574 while(*p && (ISXDIGIT(*p) || (*p == ':') || (*p == '.'))) { 575 char *endp; 576 part = strtoul(p, &endp, 16); 577 if(ISXDIGIT(*p)) 578 p = endp; 579 else 580 p++; 581 } 582 if(*p != ']') 583 logmsg("Invalid CONNECT IPv6 address format"); 584 else if(*(p + 1) != ':') 585 logmsg("Invalid CONNECT IPv6 port format"); 586 else 587 portp = p + 1; 588 589 req->testno = part; 590 } 591 else 592 portp = strchr(doc, ':'); 593 594 if(portp && (*(portp + 1) != '\0') && ISDIGIT(*(portp + 1))) { 595 unsigned long ulnum = strtoul(portp + 1, NULL, 10); 596 if(!ulnum || (ulnum > 65535UL)) 597 logmsg("Invalid CONNECT port received"); 598 else 599 req->connect_port = curlx_ultous(ulnum); 600 601 } 602 logmsg("Port number: %d, test case number: %ld", 603 req->connect_port, req->testno); 604 } 605 } 606 607 if(req->testno == DOCNUMBER_NOTHING) { 608 /* check for a Testno: header with the test case number */ 609 char *testno = strstr(line, "\nTestno: "); 610 if(testno) { 611 req->testno = strtol(&testno[9], NULL, 10); 612 logmsg("Found test number %d in Testno: header!", req->testno); 613 } 614 } 615 if(req->testno == DOCNUMBER_NOTHING) { 616 /* Still no test case number. Try to get the the number off the last dot 617 instead, IE we consider the TLD to be the test number. Test 123 can 618 then be written as "example.com.123". */ 619 620 /* find the last dot */ 621 ptr = strrchr(doc, '.'); 622 623 /* get the number after it */ 624 if(ptr) { 625 ptr++; /* skip the dot */ 626 627 req->testno = strtol(ptr, &ptr, 10); 628 629 if(req->testno > 10000) { 630 req->partno = req->testno % 10000; 631 req->testno /= 10000; 632 633 logmsg("found test %d in requested host name", req->testno); 634 635 } 636 else 637 req->partno = 0; 638 639 snprintf(logbuf, sizeof(logbuf), 640 "Requested test number %ld part %ld (from host name)", 641 req->testno, req->partno); 642 logmsg("%s", logbuf); 643 644 } 645 646 if(!req->testno) { 647 logmsg("Did not find test number in PATH"); 648 req->testno = DOCNUMBER_404; 649 } 650 else 651 parse_servercmd(req); 652 } 653 } 654 else if((req->offset >= 3) && (req->testno == DOCNUMBER_NOTHING)) { 655 logmsg("** Unusual request. Starts with %02x %02x %02x", 656 line[0], line[1], line[2]); 657 } 658 659 if(!end) { 660 /* we don't have a complete request yet! */ 661 logmsg("request not complete yet"); 662 return 0; /* not complete yet */ 663 } 664 logmsg("- request found to be complete"); 665 666 if(use_gopher) { 667 /* when using gopher we cannot check the request until the entire 668 thing has been received */ 669 char *ptr; 670 671 /* find the last slash in the line */ 672 ptr = strrchr(line, '/'); 673 674 if(ptr) { 675 ptr++; /* skip the slash */ 676 677 /* skip all non-numericals following the slash */ 678 while(*ptr && !ISDIGIT(*ptr)) 679 ptr++; 680 681 req->testno = strtol(ptr, &ptr, 10); 682 683 if(req->testno > 10000) { 684 req->partno = req->testno % 10000; 685 req->testno /= 10000; 686 } 687 else 688 req->partno = 0; 689 690 snprintf(logbuf, sizeof(logbuf), 691 "Requested GOPHER test number %ld part %ld", 692 req->testno, req->partno); 693 logmsg("%s", logbuf); 694 } 695 } 696 697 if(req->pipe) 698 /* we do have a full set, advance the checkindex to after the end of the 699 headers, for the pipelining case mostly */ 700 req->checkindex += (end - line) + strlen(end_of_headers); 701 702 /* **** Persistence **** 703 * 704 * If the request is a HTTP/1.0 one, we close the connection unconditionally 705 * when we're done. 706 * 707 * If the request is a HTTP/1.1 one, we MUST check for a "Connection:" 708 * header that might say "close". If it does, we close a connection when 709 * this request is processed. Otherwise, we keep the connection alive for X 710 * seconds. 711 */ 712 713 do { 714 if(got_exit_signal) 715 return 1; /* done */ 716 717 if((req->cl == 0) && strncasecompare("Content-Length:", line, 15)) { 718 /* If we don't ignore content-length, we read it and we read the whole 719 request including the body before we return. If we've been told to 720 ignore the content-length, we will return as soon as all headers 721 have been received */ 722 char *endptr; 723 char *ptr = line + 15; 724 unsigned long clen = 0; 725 while(*ptr && ISSPACE(*ptr)) 726 ptr++; 727 endptr = ptr; 728 errno = 0; 729 clen = strtoul(ptr, &endptr, 10); 730 if((ptr == endptr) || !ISSPACE(*endptr) || (ERANGE == errno)) { 731 /* this assumes that a zero Content-Length is valid */ 732 logmsg("Found invalid Content-Length: (%s) in the request", ptr); 733 req->open = FALSE; /* closes connection */ 734 return 1; /* done */ 735 } 736 req->cl = clen - req->skip; 737 738 logmsg("Found Content-Length: %lu in the request", clen); 739 if(req->skip) 740 logmsg("... but will abort after %zu bytes", req->cl); 741 break; 742 } 743 else if(strncasecompare("Transfer-Encoding: chunked", line, 744 strlen("Transfer-Encoding: chunked"))) { 745 /* chunked data coming in */ 746 chunked = TRUE; 747 } 748 749 if(chunked) { 750 if(strstr(req->reqbuf, "\r\n0\r\n\r\n")) 751 /* end of chunks reached */ 752 return 1; /* done */ 753 else 754 return 0; /* not done */ 755 } 756 757 line = strchr(line, '\n'); 758 if(line) 759 line++; 760 761 } while(line); 762 763 if(!req->auth && strstr(req->reqbuf, "Authorization:")) { 764 req->auth = TRUE; /* Authorization: header present! */ 765 if(req->auth_req) 766 logmsg("Authorization header found, as required"); 767 } 768 769 if(strstr(req->reqbuf, "Authorization: Negotiate")) { 770 /* Negotiate iterations */ 771 static long prev_testno = -1; 772 static long prev_partno = -1; 773 logmsg("Negotiate: prev_testno: %d, prev_partno: %d", 774 prev_testno, prev_partno); 775 if(req->testno != prev_testno) { 776 prev_testno = req->testno; 777 prev_partno = req->partno; 778 } 779 prev_partno += 1; 780 req->partno = prev_partno; 781 } 782 else if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) { 783 /* If the client is passing this Digest-header, we set the part number 784 to 1000. Not only to spice up the complexity of this, but to make 785 Digest stuff to work in the test suite. */ 786 req->partno += 1000; 787 req->digest = TRUE; /* header found */ 788 logmsg("Received Digest request, sending back data %ld", req->partno); 789 } 790 else if(!req->ntlm && 791 strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) { 792 /* If the client is passing this type-3 NTLM header */ 793 req->partno += 1002; 794 req->ntlm = TRUE; /* NTLM found */ 795 logmsg("Received NTLM type-3, sending back data %ld", req->partno); 796 if(req->cl) { 797 logmsg(" Expecting %zu POSTed bytes", req->cl); 798 } 799 } 800 else if(!req->ntlm && 801 strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) { 802 /* If the client is passing this type-1 NTLM header */ 803 req->partno += 1001; 804 req->ntlm = TRUE; /* NTLM found */ 805 logmsg("Received NTLM type-1, sending back data %ld", req->partno); 806 } 807 else if((req->partno >= 1000) && 808 strstr(req->reqbuf, "Authorization: Basic")) { 809 /* If the client is passing this Basic-header and the part number is 810 already >=1000, we add 1 to the part number. This allows simple Basic 811 authentication negotiation to work in the test suite. */ 812 req->partno += 1; 813 logmsg("Received Basic request, sending back data %ld", req->partno); 814 } 815 if(strstr(req->reqbuf, "Connection: close")) 816 req->open = FALSE; /* close connection after this request */ 817 818 if(!req->pipe && 819 req->open && 820 req->prot_version >= 11 && 821 end && 822 req->reqbuf + req->offset > end + strlen(end_of_headers) && 823 !req->cl && 824 (!strncmp(req->reqbuf, "GET", strlen("GET")) || 825 !strncmp(req->reqbuf, "HEAD", strlen("HEAD")))) { 826 /* If we have a persistent connection, HTTP version >= 1.1 827 and GET/HEAD request, enable pipelining. */ 828 req->checkindex = (end - req->reqbuf) + strlen(end_of_headers); 829 req->pipelining = TRUE; 830 } 831 832 while(req->pipe) { 833 if(got_exit_signal) 834 return 1; /* done */ 835 /* scan for more header ends within this chunk */ 836 line = &req->reqbuf[req->checkindex]; 837 end = strstr(line, end_of_headers); 838 if(!end) 839 break; 840 req->checkindex += (end - line) + strlen(end_of_headers); 841 req->pipe--; 842 } 843 844 /* If authentication is required and no auth was provided, end now. This 845 makes the server NOT wait for PUT/POST data and you can then make the 846 test case send a rejection before any such data has been sent. Test case 847 154 uses this.*/ 848 if(req->auth_req && !req->auth) { 849 logmsg("Return early due to auth requested by none provided"); 850 return 1; /* done */ 851 } 852 853 if(req->upgrade && strstr(req->reqbuf, "Upgrade:")) { 854 /* we allow upgrade and there was one! */ 855 logmsg("Found Upgrade: in request and allows it"); 856 req->upgrade_request = TRUE; 857 } 858 859 if(req->cl > 0) { 860 if(req->cl <= req->offset - (end - req->reqbuf) - strlen(end_of_headers)) 861 return 1; /* done */ 862 else 863 return 0; /* not complete yet */ 864 } 865 866 return 1; /* done */ 867 } 868 869 /* store the entire request in a file */ 870 static void storerequest(const char *reqbuf, size_t totalsize) 871 { 872 int res; 873 int error = 0; 874 size_t written; 875 size_t writeleft; 876 FILE *dump; 877 const char *dumpfile = is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP; 878 879 if(reqbuf == NULL) 880 return; 881 if(totalsize == 0) 882 return; 883 884 do { 885 dump = fopen(dumpfile, "ab"); 886 } while((dump == NULL) && ((error = errno) == EINTR)); 887 if(dump == NULL) { 888 logmsg("[2] Error opening file %s error: %d %s", 889 dumpfile, error, strerror(error)); 890 logmsg("Failed to write request input "); 891 return; 892 } 893 894 writeleft = totalsize; 895 do { 896 written = fwrite(&reqbuf[totalsize-writeleft], 897 1, writeleft, dump); 898 if(got_exit_signal) 899 goto storerequest_cleanup; 900 if(written > 0) 901 writeleft -= written; 902 } while((writeleft > 0) && ((error = errno) == EINTR)); 903 904 if(writeleft == 0) 905 logmsg("Wrote request (%zu bytes) input to %s", totalsize, dumpfile); 906 else if(writeleft > 0) { 907 logmsg("Error writing file %s error: %d %s", 908 dumpfile, error, strerror(error)); 909 logmsg("Wrote only (%zu bytes) of (%zu bytes) request input to %s", 910 totalsize-writeleft, totalsize, dumpfile); 911 } 912 913 storerequest_cleanup: 914 915 do { 916 res = fclose(dump); 917 } while(res && ((error = errno) == EINTR)); 918 if(res) 919 logmsg("Error closing file %s error: %d %s", 920 dumpfile, error, strerror(error)); 921 } 922 923 static void init_httprequest(struct httprequest *req) 924 { 925 /* Pipelining is already set, so do not initialize it here. Only initialize 926 checkindex and offset if pipelining is not set, since in a pipeline they 927 need to be inherited from the previous request. */ 928 if(!req->pipelining) { 929 req->checkindex = 0; 930 req->offset = 0; 931 } 932 req->testno = DOCNUMBER_NOTHING; 933 req->partno = 0; 934 req->connect_request = FALSE; 935 req->open = TRUE; 936 req->auth_req = FALSE; 937 req->auth = FALSE; 938 req->cl = 0; 939 req->digest = FALSE; 940 req->ntlm = FALSE; 941 req->pipe = 0; 942 req->skip = 0; 943 req->writedelay = 0; 944 req->rcmd = RCMD_NORMALREQ; 945 req->prot_version = 0; 946 req->callcount = 0; 947 req->connect_port = 0; 948 req->done_processing = 0; 949 req->upgrade = 0; 950 req->upgrade_request = 0; 951 } 952 953 /* returns 1 if the connection should be serviced again immediately, 0 if there 954 is no data waiting, or < 0 if it should be closed */ 955 static int get_request(curl_socket_t sock, struct httprequest *req) 956 { 957 int error; 958 int fail = 0; 959 char *reqbuf = req->reqbuf; 960 ssize_t got = 0; 961 int overflow = 0; 962 963 char *pipereq = NULL; 964 size_t pipereq_length = 0; 965 966 if(req->pipelining) { 967 pipereq = reqbuf + req->checkindex; 968 pipereq_length = req->offset - req->checkindex; 969 970 /* Now that we've got the pipelining info we can reset the 971 pipelining-related vars which were skipped in init_httprequest */ 972 req->pipelining = FALSE; 973 req->checkindex = 0; 974 req->offset = 0; 975 } 976 977 if(req->offset >= REQBUFSIZ-1) { 978 /* buffer is already full; do nothing */ 979 overflow = 1; 980 } 981 else { 982 if(pipereq_length && pipereq) { 983 memmove(reqbuf, pipereq, pipereq_length); 984 got = curlx_uztosz(pipereq_length); 985 pipereq_length = 0; 986 } 987 else { 988 if(req->skip) 989 /* we are instructed to not read the entire thing, so we make sure to 990 only read what we're supposed to and NOT read the enire thing the 991 client wants to send! */ 992 got = sread(sock, reqbuf + req->offset, req->cl); 993 else 994 got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset); 995 } 996 if(got_exit_signal) 997 return -1; 998 if(got == 0) { 999 logmsg("Connection closed by client"); 1000 fail = 1; 1001 } 1002 else if(got < 0) { 1003 error = SOCKERRNO; 1004 if(EAGAIN == error || EWOULDBLOCK == error) { 1005 /* nothing to read at the moment */ 1006 return 0; 1007 } 1008 logmsg("recv() returned error: (%d) %s", error, strerror(error)); 1009 fail = 1; 1010 } 1011 if(fail) { 1012 /* dump the request received so far to the external file */ 1013 reqbuf[req->offset] = '\0'; 1014 storerequest(reqbuf, req->offset); 1015 return -1; 1016 } 1017 1018 logmsg("Read %zd bytes", got); 1019 1020 req->offset += (size_t)got; 1021 reqbuf[req->offset] = '\0'; 1022 1023 req->done_processing = ProcessRequest(req); 1024 if(got_exit_signal) 1025 return -1; 1026 if(req->done_processing && req->pipe) { 1027 logmsg("Waiting for another piped request"); 1028 req->done_processing = 0; 1029 req->pipe--; 1030 } 1031 } 1032 1033 if(overflow || (req->offset == REQBUFSIZ-1 && got > 0)) { 1034 logmsg("Request would overflow buffer, closing connection"); 1035 /* dump request received so far to external file anyway */ 1036 reqbuf[REQBUFSIZ-1] = '\0'; 1037 fail = 1; 1038 } 1039 else if(req->offset > REQBUFSIZ-1) { 1040 logmsg("Request buffer overflow, closing connection"); 1041 /* dump request received so far to external file anyway */ 1042 reqbuf[REQBUFSIZ-1] = '\0'; 1043 fail = 1; 1044 } 1045 else 1046 reqbuf[req->offset] = '\0'; 1047 1048 /* at the end of a request dump it to an external file */ 1049 if(fail || req->done_processing) 1050 storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset); 1051 if(got_exit_signal) 1052 return -1; 1053 1054 return fail ? -1 : 1; 1055 } 1056 1057 /* returns -1 on failure */ 1058 static int send_doc(curl_socket_t sock, struct httprequest *req) 1059 { 1060 ssize_t written; 1061 size_t count; 1062 const char *buffer; 1063 char *ptr = NULL; 1064 FILE *stream; 1065 char *cmd = NULL; 1066 size_t cmdsize = 0; 1067 FILE *dump; 1068 bool persistant = TRUE; 1069 bool sendfailure = FALSE; 1070 size_t responsesize; 1071 int error = 0; 1072 int res; 1073 const char *responsedump = is_proxy?RESPONSE_PROXY_DUMP:RESPONSE_DUMP; 1074 static char weare[256]; 1075 1076 switch(req->rcmd) { 1077 default: 1078 case RCMD_NORMALREQ: 1079 break; /* continue with business as usual */ 1080 case RCMD_STREAM: 1081 #define STREAMTHIS "a string to stream 01234567890\n" 1082 count = strlen(STREAMTHIS); 1083 for(;;) { 1084 written = swrite(sock, STREAMTHIS, count); 1085 if(got_exit_signal) 1086 return -1; 1087 if(written != (ssize_t)count) { 1088 logmsg("Stopped streaming"); 1089 break; 1090 } 1091 } 1092 return -1; 1093 case RCMD_IDLE: 1094 /* Do nothing. Sit idle. Pretend it rains. */ 1095 return 0; 1096 } 1097 1098 req->open = FALSE; 1099 1100 if(req->testno < 0) { 1101 size_t msglen; 1102 char msgbuf[64]; 1103 1104 switch(req->testno) { 1105 case DOCNUMBER_QUIT: 1106 logmsg("Replying to QUIT"); 1107 buffer = docquit; 1108 break; 1109 case DOCNUMBER_WERULEZ: 1110 /* we got a "friends?" question, reply back that we sure are */ 1111 logmsg("Identifying ourselves as friends"); 1112 snprintf(msgbuf, sizeof(msgbuf), "WE ROOLZ: %ld\r\n", (long)getpid()); 1113 msglen = strlen(msgbuf); 1114 if(use_gopher) 1115 snprintf(weare, sizeof(weare), "%s", msgbuf); 1116 else 1117 snprintf(weare, sizeof(weare), 1118 "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s", 1119 msglen, msgbuf); 1120 buffer = weare; 1121 break; 1122 case DOCNUMBER_404: 1123 default: 1124 logmsg("Replying to with a 404"); 1125 buffer = doc404; 1126 break; 1127 } 1128 1129 count = strlen(buffer); 1130 } 1131 else { 1132 char partbuf[80]; 1133 char *filename = test2file(req->testno); 1134 1135 /* select the <data> tag for "normal" requests and the <connect> one 1136 for CONNECT requests (within the <reply> section) */ 1137 const char *section = req->connect_request?"connect":"data"; 1138 1139 if(req->partno) 1140 snprintf(partbuf, sizeof(partbuf), "%s%ld", section, req->partno); 1141 else 1142 snprintf(partbuf, sizeof(partbuf), "%s", section); 1143 1144 logmsg("Send response test%ld section <%s>", req->testno, partbuf); 1145 1146 stream = fopen(filename, "rb"); 1147 if(!stream) { 1148 error = errno; 1149 logmsg("fopen() failed with error: %d %s", error, strerror(error)); 1150 logmsg(" [3] Error opening file: %s", filename); 1151 return 0; 1152 } 1153 else { 1154 error = getpart(&ptr, &count, "reply", partbuf, stream); 1155 fclose(stream); 1156 if(error) { 1157 logmsg("getpart() failed with error: %d", error); 1158 return 0; 1159 } 1160 buffer = ptr; 1161 } 1162 1163 if(got_exit_signal) { 1164 free(ptr); 1165 return -1; 1166 } 1167 1168 /* re-open the same file again */ 1169 stream = fopen(filename, "rb"); 1170 if(!stream) { 1171 error = errno; 1172 logmsg("fopen() failed with error: %d %s", error, strerror(error)); 1173 logmsg(" [4] Error opening file: %s", filename); 1174 free(ptr); 1175 return 0; 1176 } 1177 else { 1178 /* get the custom server control "commands" */ 1179 error = getpart(&cmd, &cmdsize, "reply", "postcmd", stream); 1180 fclose(stream); 1181 if(error) { 1182 logmsg("getpart() failed with error: %d", error); 1183 free(ptr); 1184 return 0; 1185 } 1186 } 1187 } 1188 1189 if(got_exit_signal) { 1190 free(ptr); 1191 free(cmd); 1192 return -1; 1193 } 1194 1195 /* If the word 'swsclose' is present anywhere in the reply chunk, the 1196 connection will be closed after the data has been sent to the requesting 1197 client... */ 1198 if(strstr(buffer, "swsclose") || !count) { 1199 persistant = FALSE; 1200 logmsg("connection close instruction \"swsclose\" found in response"); 1201 } 1202 if(strstr(buffer, "swsbounce")) { 1203 prevbounce = TRUE; 1204 logmsg("enable \"swsbounce\" in the next request"); 1205 } 1206 else 1207 prevbounce = FALSE; 1208 1209 dump = fopen(responsedump, "ab"); 1210 if(!dump) { 1211 error = errno; 1212 logmsg("fopen() failed with error: %d %s", error, strerror(error)); 1213 logmsg(" [5] Error opening file: %s", responsedump); 1214 free(ptr); 1215 free(cmd); 1216 return -1; 1217 } 1218 1219 responsesize = count; 1220 do { 1221 /* Ok, we send no more than N bytes at a time, just to make sure that 1222 larger chunks are split up so that the client will need to do multiple 1223 recv() calls to get it and thus we exercise that code better */ 1224 size_t num = count; 1225 if(num > 20) 1226 num = 20; 1227 1228 retry: 1229 written = swrite(sock, buffer, num); 1230 if(written < 0) { 1231 if((EWOULDBLOCK == SOCKERRNO) || (EAGAIN == SOCKERRNO)) { 1232 wait_ms(10); 1233 goto retry; 1234 } 1235 sendfailure = TRUE; 1236 break; 1237 } 1238 1239 /* write to file as well */ 1240 fwrite(buffer, 1, (size_t)written, dump); 1241 1242 count -= written; 1243 buffer += written; 1244 1245 if(req->writedelay) { 1246 int quarters = req->writedelay * 4; 1247 logmsg("Pausing %d seconds", req->writedelay); 1248 while((quarters > 0) && !got_exit_signal) { 1249 quarters--; 1250 wait_ms(250); 1251 } 1252 } 1253 } while((count > 0) && !got_exit_signal); 1254 1255 do { 1256 res = fclose(dump); 1257 } while(res && ((error = errno) == EINTR)); 1258 if(res) 1259 logmsg("Error closing file %s error: %d %s", 1260 responsedump, error, strerror(error)); 1261 1262 if(got_exit_signal) { 1263 free(ptr); 1264 free(cmd); 1265 return -1; 1266 } 1267 1268 if(sendfailure) { 1269 logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) " 1270 "were sent", 1271 responsesize-count, responsesize); 1272 free(ptr); 1273 free(cmd); 1274 return -1; 1275 } 1276 1277 logmsg("Response sent (%zu bytes) and written to %s", 1278 responsesize, responsedump); 1279 free(ptr); 1280 1281 if(cmdsize > 0) { 1282 char command[32]; 1283 int quarters; 1284 int num; 1285 ptr = cmd; 1286 do { 1287 if(2 == sscanf(ptr, "%31s %d", command, &num)) { 1288 if(!strcmp("wait", command)) { 1289 logmsg("Told to sleep for %d seconds", num); 1290 quarters = num * 4; 1291 while((quarters > 0) && !got_exit_signal) { 1292 quarters--; 1293 res = wait_ms(250); 1294 if(res) { 1295 /* should not happen */ 1296 error = errno; 1297 logmsg("wait_ms() failed with error: (%d) %s", 1298 error, strerror(error)); 1299 break; 1300 } 1301 } 1302 if(!quarters) 1303 logmsg("Continuing after sleeping %d seconds", num); 1304 } 1305 else 1306 logmsg("Unknown command in reply command section"); 1307 } 1308 ptr = strchr(ptr, '\n'); 1309 if(ptr) 1310 ptr++; 1311 else 1312 ptr = NULL; 1313 } while(ptr && *ptr); 1314 } 1315 free(cmd); 1316 req->open = use_gopher?FALSE:persistant; 1317 1318 prevtestno = req->testno; 1319 prevpartno = req->partno; 1320 1321 return 0; 1322 } 1323 1324 static curl_socket_t connect_to(const char *ipaddr, unsigned short port) 1325 { 1326 srvr_sockaddr_union_t serveraddr; 1327 curl_socket_t serverfd; 1328 int error; 1329 int rc = 0; 1330 const char *op_br = ""; 1331 const char *cl_br = ""; 1332 1333 #ifdef ENABLE_IPV6 1334 if(socket_domain == AF_INET6) { 1335 op_br = "["; 1336 cl_br = "]"; 1337 } 1338 #endif 1339 1340 if(!ipaddr) 1341 return CURL_SOCKET_BAD; 1342 1343 logmsg("about to connect to %s%s%s:%hu", 1344 op_br, ipaddr, cl_br, port); 1345 1346 1347 serverfd = socket(socket_domain, SOCK_STREAM, 0); 1348 if(CURL_SOCKET_BAD == serverfd) { 1349 error = SOCKERRNO; 1350 logmsg("Error creating socket for server conection: (%d) %s", 1351 error, strerror(error)); 1352 return CURL_SOCKET_BAD; 1353 } 1354 1355 #ifdef TCP_NODELAY 1356 if(socket_domain_is_ip()) { 1357 /* Disable the Nagle algorithm */ 1358 curl_socklen_t flag = 1; 1359 if(0 != setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, 1360 (void *)&flag, sizeof(flag))) 1361 logmsg("====> TCP_NODELAY for server conection failed"); 1362 } 1363 #endif 1364 1365 switch(socket_domain) { 1366 case AF_INET: 1367 memset(&serveraddr.sa4, 0, sizeof(serveraddr.sa4)); 1368 serveraddr.sa4.sin_family = AF_INET; 1369 serveraddr.sa4.sin_port = htons(port); 1370 if(Curl_inet_pton(AF_INET, ipaddr, &serveraddr.sa4.sin_addr) < 1) { 1371 logmsg("Error inet_pton failed AF_INET conversion of '%s'", ipaddr); 1372 sclose(serverfd); 1373 return CURL_SOCKET_BAD; 1374 } 1375 1376 rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa4)); 1377 break; 1378 #ifdef ENABLE_IPV6 1379 case AF_INET6: 1380 memset(&serveraddr.sa6, 0, sizeof(serveraddr.sa6)); 1381 serveraddr.sa6.sin6_family = AF_INET6; 1382 serveraddr.sa6.sin6_port = htons(port); 1383 if(Curl_inet_pton(AF_INET6, ipaddr, &serveraddr.sa6.sin6_addr) < 1) { 1384 logmsg("Error inet_pton failed AF_INET6 conversion of '%s'", ipaddr); 1385 sclose(serverfd); 1386 return CURL_SOCKET_BAD; 1387 } 1388 1389 rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa6)); 1390 break; 1391 #endif /* ENABLE_IPV6 */ 1392 #ifdef USE_UNIX_SOCKETS 1393 case AF_UNIX: 1394 logmsg("Proxying through Unix socket is not (yet?) supported."); 1395 return CURL_SOCKET_BAD; 1396 #endif /* USE_UNIX_SOCKETS */ 1397 } 1398 1399 if(got_exit_signal) { 1400 sclose(serverfd); 1401 return CURL_SOCKET_BAD; 1402 } 1403 1404 if(rc) { 1405 error = SOCKERRNO; 1406 logmsg("Error connecting to server port %hu: (%d) %s", 1407 port, error, strerror(error)); 1408 sclose(serverfd); 1409 return CURL_SOCKET_BAD; 1410 } 1411 1412 logmsg("connected fine to %s%s%s:%hu, now tunnel", 1413 op_br, ipaddr, cl_br, port); 1414 1415 return serverfd; 1416 } 1417 1418 /* 1419 * A CONNECT has been received, a CONNECT response has been sent. 1420 * 1421 * This function needs to connect to the server, and then pass data between 1422 * the client and the server back and forth until the connection is closed by 1423 * either end. 1424 * 1425 * When doing FTP through a CONNECT proxy, we expect that the data connection 1426 * will be setup while the first connect is still being kept up. Therefor we 1427 * must accept a new connection and deal with it appropriately. 1428 */ 1429 1430 #define data_or_ctrl(x) ((x)?"DATA":"CTRL") 1431 1432 #define CTRL 0 1433 #define DATA 1 1434 1435 static void http_connect(curl_socket_t *infdp, 1436 curl_socket_t rootfd, 1437 const char *ipaddr, 1438 unsigned short ipport) 1439 { 1440 curl_socket_t serverfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD}; 1441 curl_socket_t clientfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD}; 1442 ssize_t toc[2] = {0, 0}; /* number of bytes to client */ 1443 ssize_t tos[2] = {0, 0}; /* number of bytes to server */ 1444 char readclient[2][256]; 1445 char readserver[2][256]; 1446 bool poll_client_rd[2] = { TRUE, TRUE }; 1447 bool poll_server_rd[2] = { TRUE, TRUE }; 1448 bool poll_client_wr[2] = { TRUE, TRUE }; 1449 bool poll_server_wr[2] = { TRUE, TRUE }; 1450 bool primary = FALSE; 1451 bool secondary = FALSE; 1452 int max_tunnel_idx; /* CTRL or DATA */ 1453 int loop; 1454 int i; 1455 int timeout_count = 0; 1456 1457 /* primary tunnel client endpoint already connected */ 1458 clientfd[CTRL] = *infdp; 1459 1460 /* Sleep here to make sure the client reads CONNECT response's 1461 'end of headers' separate from the server data that follows. 1462 This is done to prevent triggering libcurl known bug #39. */ 1463 for(loop = 2; (loop > 0) && !got_exit_signal; loop--) 1464 wait_ms(250); 1465 if(got_exit_signal) 1466 goto http_connect_cleanup; 1467 1468 serverfd[CTRL] = connect_to(ipaddr, ipport); 1469 if(serverfd[CTRL] == CURL_SOCKET_BAD) 1470 goto http_connect_cleanup; 1471 1472 /* Primary tunnel socket endpoints are now connected. Tunnel data back and 1473 forth over the primary tunnel until client or server breaks the primary 1474 tunnel, simultaneously allowing establishment, operation and teardown of 1475 a secondary tunnel that may be used for passive FTP data connection. */ 1476 1477 max_tunnel_idx = CTRL; 1478 primary = TRUE; 1479 1480 while(!got_exit_signal) { 1481 1482 fd_set input; 1483 fd_set output; 1484 struct timeval timeout = {1, 0}; /* 1000 ms */ 1485 ssize_t rc; 1486 curl_socket_t maxfd = (curl_socket_t)-1; 1487 1488 FD_ZERO(&input); 1489 FD_ZERO(&output); 1490 1491 if((clientfd[DATA] == CURL_SOCKET_BAD) && 1492 (serverfd[DATA] == CURL_SOCKET_BAD) && 1493 poll_client_rd[CTRL] && poll_client_wr[CTRL] && 1494 poll_server_rd[CTRL] && poll_server_wr[CTRL]) { 1495 /* listener socket is monitored to allow client to establish 1496 secondary tunnel only when this tunnel is not established 1497 and primary one is fully operational */ 1498 FD_SET(rootfd, &input); 1499 maxfd = rootfd; 1500 } 1501 1502 /* set tunnel sockets to wait for */ 1503 for(i = 0; i <= max_tunnel_idx; i++) { 1504 /* client side socket monitoring */ 1505 if(clientfd[i] != CURL_SOCKET_BAD) { 1506 if(poll_client_rd[i]) { 1507 /* unless told not to do so, monitor readability */ 1508 FD_SET(clientfd[i], &input); 1509 if(clientfd[i] > maxfd) 1510 maxfd = clientfd[i]; 1511 } 1512 if(poll_client_wr[i] && toc[i]) { 1513 /* unless told not to do so, monitor writability 1514 if there is data ready to be sent to client */ 1515 FD_SET(clientfd[i], &output); 1516 if(clientfd[i] > maxfd) 1517 maxfd = clientfd[i]; 1518 } 1519 } 1520 /* server side socket monitoring */ 1521 if(serverfd[i] != CURL_SOCKET_BAD) { 1522 if(poll_server_rd[i]) { 1523 /* unless told not to do so, monitor readability */ 1524 FD_SET(serverfd[i], &input); 1525 if(serverfd[i] > maxfd) 1526 maxfd = serverfd[i]; 1527 } 1528 if(poll_server_wr[i] && tos[i]) { 1529 /* unless told not to do so, monitor writability 1530 if there is data ready to be sent to server */ 1531 FD_SET(serverfd[i], &output); 1532 if(serverfd[i] > maxfd) 1533 maxfd = serverfd[i]; 1534 } 1535 } 1536 } 1537 if(got_exit_signal) 1538 break; 1539 1540 rc = select((int)maxfd + 1, &input, &output, NULL, &timeout); 1541 1542 if(rc > 0) { 1543 /* socket action */ 1544 bool tcp_fin_wr; 1545 timeout_count = 0; 1546 1547 if(got_exit_signal) 1548 break; 1549 1550 tcp_fin_wr = FALSE; 1551 1552 /* ---------------------------------------------------------- */ 1553 1554 /* passive mode FTP may establish a secondary tunnel */ 1555 if((clientfd[DATA] == CURL_SOCKET_BAD) && 1556 (serverfd[DATA] == CURL_SOCKET_BAD) && FD_ISSET(rootfd, &input)) { 1557 /* a new connection on listener socket (most likely from client) */ 1558 curl_socket_t datafd = accept(rootfd, NULL, NULL); 1559 if(datafd != CURL_SOCKET_BAD) { 1560 struct httprequest req2; 1561 int err = 0; 1562 memset(&req2, 0, sizeof(req2)); 1563 logmsg("====> Client connect DATA"); 1564 #ifdef TCP_NODELAY 1565 if(socket_domain_is_ip()) { 1566 /* Disable the Nagle algorithm */ 1567 curl_socklen_t flag = 1; 1568 if(0 != setsockopt(datafd, IPPROTO_TCP, TCP_NODELAY, 1569 (void *)&flag, sizeof(flag))) 1570 logmsg("====> TCP_NODELAY for client DATA conection failed"); 1571 } 1572 #endif 1573 req2.pipelining = FALSE; 1574 init_httprequest(&req2); 1575 while(!req2.done_processing) { 1576 err = get_request(datafd, &req2); 1577 if(err < 0) { 1578 /* this socket must be closed, done or not */ 1579 break; 1580 } 1581 } 1582 1583 /* skip this and close the socket if err < 0 */ 1584 if(err >= 0) { 1585 err = send_doc(datafd, &req2); 1586 if(!err && req2.connect_request) { 1587 /* sleep to prevent triggering libcurl known bug #39. */ 1588 for(loop = 2; (loop > 0) && !got_exit_signal; loop--) 1589 wait_ms(250); 1590 if(!got_exit_signal) { 1591 /* connect to the server */ 1592 serverfd[DATA] = connect_to(ipaddr, req2.connect_port); 1593 if(serverfd[DATA] != CURL_SOCKET_BAD) { 1594 /* secondary tunnel established, now we have two 1595 connections */ 1596 poll_client_rd[DATA] = TRUE; 1597 poll_client_wr[DATA] = TRUE; 1598 poll_server_rd[DATA] = TRUE; 1599 poll_server_wr[DATA] = TRUE; 1600 max_tunnel_idx = DATA; 1601 secondary = TRUE; 1602 toc[DATA] = 0; 1603 tos[DATA] = 0; 1604 clientfd[DATA] = datafd; 1605 datafd = CURL_SOCKET_BAD; 1606 } 1607 } 1608 } 1609 } 1610 if(datafd != CURL_SOCKET_BAD) { 1611 /* secondary tunnel not established */ 1612 shutdown(datafd, SHUT_RDWR); 1613 sclose(datafd); 1614 } 1615 } 1616 if(got_exit_signal) 1617 break; 1618 } 1619 1620 /* ---------------------------------------------------------- */ 1621 1622 /* react to tunnel endpoint readable/writable notifications */ 1623 for(i = 0; i <= max_tunnel_idx; i++) { 1624 size_t len; 1625 if(clientfd[i] != CURL_SOCKET_BAD) { 1626 len = sizeof(readclient[i]) - tos[i]; 1627 if(len && FD_ISSET(clientfd[i], &input)) { 1628 /* read from client */ 1629 rc = sread(clientfd[i], &readclient[i][tos[i]], len); 1630 if(rc <= 0) { 1631 logmsg("[%s] got %zd, STOP READING client", data_or_ctrl(i), rc); 1632 shutdown(clientfd[i], SHUT_RD); 1633 poll_client_rd[i] = FALSE; 1634 } 1635 else { 1636 logmsg("[%s] READ %zd bytes from client", data_or_ctrl(i), rc); 1637 logmsg("[%s] READ \"%s\"", data_or_ctrl(i), 1638 data_to_hex(&readclient[i][tos[i]], rc)); 1639 tos[i] += rc; 1640 } 1641 } 1642 } 1643 if(serverfd[i] != CURL_SOCKET_BAD) { 1644 len = sizeof(readserver[i])-toc[i]; 1645 if(len && FD_ISSET(serverfd[i], &input)) { 1646 /* read from server */ 1647 rc = sread(serverfd[i], &readserver[i][toc[i]], len); 1648 if(rc <= 0) { 1649 logmsg("[%s] got %zd, STOP READING server", data_or_ctrl(i), rc); 1650 shutdown(serverfd[i], SHUT_RD); 1651 poll_server_rd[i] = FALSE; 1652 } 1653 else { 1654 logmsg("[%s] READ %zd bytes from server", data_or_ctrl(i), rc); 1655 logmsg("[%s] READ \"%s\"", data_or_ctrl(i), 1656 data_to_hex(&readserver[i][toc[i]], rc)); 1657 toc[i] += rc; 1658 } 1659 } 1660 } 1661 if(clientfd[i] != CURL_SOCKET_BAD) { 1662 if(toc[i] && FD_ISSET(clientfd[i], &output)) { 1663 /* write to client */ 1664 rc = swrite(clientfd[i], readserver[i], toc[i]); 1665 if(rc <= 0) { 1666 logmsg("[%s] got %zd, STOP WRITING client", data_or_ctrl(i), rc); 1667 shutdown(clientfd[i], SHUT_WR); 1668 poll_client_wr[i] = FALSE; 1669 tcp_fin_wr = TRUE; 1670 } 1671 else { 1672 logmsg("[%s] SENT %zd bytes to client", data_or_ctrl(i), rc); 1673 logmsg("[%s] SENT \"%s\"", data_or_ctrl(i), 1674 data_to_hex(readserver[i], rc)); 1675 if(toc[i] - rc) 1676 memmove(&readserver[i][0], &readserver[i][rc], toc[i]-rc); 1677 toc[i] -= rc; 1678 } 1679 } 1680 } 1681 if(serverfd[i] != CURL_SOCKET_BAD) { 1682 if(tos[i] && FD_ISSET(serverfd[i], &output)) { 1683 /* write to server */ 1684 rc = swrite(serverfd[i], readclient[i], tos[i]); 1685 if(rc <= 0) { 1686 logmsg("[%s] got %zd, STOP WRITING server", data_or_ctrl(i), rc); 1687 shutdown(serverfd[i], SHUT_WR); 1688 poll_server_wr[i] = FALSE; 1689 tcp_fin_wr = TRUE; 1690 } 1691 else { 1692 logmsg("[%s] SENT %zd bytes to server", data_or_ctrl(i), rc); 1693 logmsg("[%s] SENT \"%s\"", data_or_ctrl(i), 1694 data_to_hex(readclient[i], rc)); 1695 if(tos[i] - rc) 1696 memmove(&readclient[i][0], &readclient[i][rc], tos[i]-rc); 1697 tos[i] -= rc; 1698 } 1699 } 1700 } 1701 } 1702 if(got_exit_signal) 1703 break; 1704 1705 /* ---------------------------------------------------------- */ 1706 1707 /* endpoint read/write disabling, endpoint closing and tunnel teardown */ 1708 for(i = 0; i <= max_tunnel_idx; i++) { 1709 for(loop = 2; loop > 0; loop--) { 1710 /* loop twice to satisfy condition interdependencies without 1711 having to await select timeout or another socket event */ 1712 if(clientfd[i] != CURL_SOCKET_BAD) { 1713 if(poll_client_rd[i] && !poll_server_wr[i]) { 1714 logmsg("[%s] DISABLED READING client", data_or_ctrl(i)); 1715 shutdown(clientfd[i], SHUT_RD); 1716 poll_client_rd[i] = FALSE; 1717 } 1718 if(poll_client_wr[i] && !poll_server_rd[i] && !toc[i]) { 1719 logmsg("[%s] DISABLED WRITING client", data_or_ctrl(i)); 1720 shutdown(clientfd[i], SHUT_WR); 1721 poll_client_wr[i] = FALSE; 1722 tcp_fin_wr = TRUE; 1723 } 1724 } 1725 if(serverfd[i] != CURL_SOCKET_BAD) { 1726 if(poll_server_rd[i] && !poll_client_wr[i]) { 1727 logmsg("[%s] DISABLED READING server", data_or_ctrl(i)); 1728 shutdown(serverfd[i], SHUT_RD); 1729 poll_server_rd[i] = FALSE; 1730 } 1731 if(poll_server_wr[i] && !poll_client_rd[i] && !tos[i]) { 1732 logmsg("[%s] DISABLED WRITING server", data_or_ctrl(i)); 1733 shutdown(serverfd[i], SHUT_WR); 1734 poll_server_wr[i] = FALSE; 1735 tcp_fin_wr = TRUE; 1736 } 1737 } 1738 } 1739 } 1740 1741 if(tcp_fin_wr) 1742 /* allow kernel to place FIN bit packet on the wire */ 1743 wait_ms(250); 1744 1745 /* socket clearing */ 1746 for(i = 0; i <= max_tunnel_idx; i++) { 1747 for(loop = 2; loop > 0; loop--) { 1748 if(clientfd[i] != CURL_SOCKET_BAD) { 1749 if(!poll_client_wr[i] && !poll_client_rd[i]) { 1750 logmsg("[%s] CLOSING client socket", data_or_ctrl(i)); 1751 sclose(clientfd[i]); 1752 clientfd[i] = CURL_SOCKET_BAD; 1753 if(serverfd[i] == CURL_SOCKET_BAD) { 1754 logmsg("[%s] ENDING", data_or_ctrl(i)); 1755 if(i == DATA) 1756 secondary = FALSE; 1757 else 1758 primary = FALSE; 1759 } 1760 } 1761 } 1762 if(serverfd[i] != CURL_SOCKET_BAD) { 1763 if(!poll_server_wr[i] && !poll_server_rd[i]) { 1764 logmsg("[%s] CLOSING server socket", data_or_ctrl(i)); 1765 sclose(serverfd[i]); 1766 serverfd[i] = CURL_SOCKET_BAD; 1767 if(clientfd[i] == CURL_SOCKET_BAD) { 1768 logmsg("[%s] ENDING", data_or_ctrl(i)); 1769 if(i == DATA) 1770 secondary = FALSE; 1771 else 1772 primary = FALSE; 1773 } 1774 } 1775 } 1776 } 1777 } 1778 1779 /* ---------------------------------------------------------- */ 1780 1781 max_tunnel_idx = secondary ? DATA : CTRL; 1782 1783 if(!primary) 1784 /* exit loop upon primary tunnel teardown */ 1785 break; 1786 1787 } /* (rc > 0) */ 1788 else { 1789 timeout_count++; 1790 if(timeout_count > 5) { 1791 logmsg("CONNECT proxy timeout after %d idle seconds!", timeout_count); 1792 break; 1793 } 1794 } 1795 } 1796 1797 http_connect_cleanup: 1798 1799 for(i = DATA; i >= CTRL; i--) { 1800 if(serverfd[i] != CURL_SOCKET_BAD) { 1801 logmsg("[%s] CLOSING server socket (cleanup)", data_or_ctrl(i)); 1802 shutdown(serverfd[i], SHUT_RDWR); 1803 sclose(serverfd[i]); 1804 } 1805 if(clientfd[i] != CURL_SOCKET_BAD) { 1806 logmsg("[%s] CLOSING client socket (cleanup)", data_or_ctrl(i)); 1807 shutdown(clientfd[i], SHUT_RDWR); 1808 sclose(clientfd[i]); 1809 } 1810 if((serverfd[i] != CURL_SOCKET_BAD) || 1811 (clientfd[i] != CURL_SOCKET_BAD)) { 1812 logmsg("[%s] ABORTING", data_or_ctrl(i)); 1813 } 1814 } 1815 1816 *infdp = CURL_SOCKET_BAD; 1817 } 1818 1819 static void http2(struct httprequest *req) 1820 { 1821 (void)req; 1822 logmsg("switched to http2"); 1823 /* left to implement */ 1824 } 1825 1826 1827 /* returns a socket handle, or 0 if there are no more waiting sockets, 1828 or < 0 if there was an error */ 1829 static curl_socket_t accept_connection(curl_socket_t sock) 1830 { 1831 curl_socket_t msgsock = CURL_SOCKET_BAD; 1832 int error; 1833 int flag = 1; 1834 1835 if(MAX_SOCKETS == num_sockets) { 1836 logmsg("Too many open sockets!"); 1837 return CURL_SOCKET_BAD; 1838 } 1839 1840 msgsock = accept(sock, NULL, NULL); 1841 1842 if(got_exit_signal) { 1843 if(CURL_SOCKET_BAD != msgsock) 1844 sclose(msgsock); 1845 return CURL_SOCKET_BAD; 1846 } 1847 1848 if(CURL_SOCKET_BAD == msgsock) { 1849 error = SOCKERRNO; 1850 if(EAGAIN == error || EWOULDBLOCK == error) { 1851 /* nothing to accept */ 1852 return 0; 1853 } 1854 logmsg("MAJOR ERROR: accept() failed with error: (%d) %s", 1855 error, strerror(error)); 1856 return CURL_SOCKET_BAD; 1857 } 1858 1859 if(0 != curlx_nonblock(msgsock, TRUE)) { 1860 error = SOCKERRNO; 1861 logmsg("curlx_nonblock failed with error: (%d) %s", 1862 error, strerror(error)); 1863 sclose(msgsock); 1864 return CURL_SOCKET_BAD; 1865 } 1866 1867 if(0 != setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, 1868 (void *)&flag, sizeof(flag))) { 1869 error = SOCKERRNO; 1870 logmsg("setsockopt(SO_KEEPALIVE) failed with error: (%d) %s", 1871 error, strerror(error)); 1872 sclose(msgsock); 1873 return CURL_SOCKET_BAD; 1874 } 1875 1876 /* 1877 ** As soon as this server accepts a connection from the test harness it 1878 ** must set the server logs advisor read lock to indicate that server 1879 ** logs should not be read until this lock is removed by this server. 1880 */ 1881 1882 if(!serverlogslocked) 1883 set_advisor_read_lock(SERVERLOGS_LOCK); 1884 serverlogslocked += 1; 1885 1886 logmsg("====> Client connect"); 1887 1888 all_sockets[num_sockets] = msgsock; 1889 num_sockets += 1; 1890 1891 #ifdef TCP_NODELAY 1892 if(socket_domain_is_ip()) { 1893 /* 1894 * Disable the Nagle algorithm to make it easier to send out a large 1895 * response in many small segments to torture the clients more. 1896 */ 1897 if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, 1898 (void *)&flag, sizeof(flag))) 1899 logmsg("====> TCP_NODELAY failed"); 1900 } 1901 #endif 1902 1903 return msgsock; 1904 } 1905 1906 /* returns 1 if the connection should be serviced again immediately, 0 if there 1907 is no data waiting, or < 0 if it should be closed */ 1908 static int service_connection(curl_socket_t msgsock, struct httprequest *req, 1909 curl_socket_t listensock, 1910 const char *connecthost) 1911 { 1912 if(got_exit_signal) 1913 return -1; 1914 1915 while(!req->done_processing) { 1916 int rc = get_request(msgsock, req); 1917 if(rc <= 0) { 1918 /* Nothing further to read now, possibly because the socket was closed */ 1919 return rc; 1920 } 1921 } 1922 1923 if(prevbounce) { 1924 /* bounce treatment requested */ 1925 if((req->testno == prevtestno) && 1926 (req->partno == prevpartno)) { 1927 req->partno++; 1928 logmsg("BOUNCE part number to %ld", req->partno); 1929 } 1930 else { 1931 prevbounce = FALSE; 1932 prevtestno = -1; 1933 prevpartno = -1; 1934 } 1935 } 1936 1937 send_doc(msgsock, req); 1938 if(got_exit_signal) 1939 return -1; 1940 1941 if(req->testno < 0) { 1942 logmsg("special request received, no persistency"); 1943 return -1; 1944 } 1945 if(!req->open) { 1946 logmsg("instructed to close connection after server-reply"); 1947 return -1; 1948 } 1949 1950 if(req->connect_request) { 1951 /* a CONNECT request, setup and talk the tunnel */ 1952 if(!is_proxy) { 1953 logmsg("received CONNECT but isn't running as proxy!"); 1954 return 1; 1955 } 1956 else { 1957 http_connect(&msgsock, listensock, connecthost, req->connect_port); 1958 return -1; 1959 } 1960 } 1961 1962 if(req->upgrade_request) { 1963 /* an upgrade request, switch to http2 here */ 1964 http2(req); 1965 return -1; 1966 } 1967 1968 /* if we got a CONNECT, loop and get another request as well! */ 1969 1970 if(req->open) { 1971 logmsg("=> persistant connection request ended, awaits new request\n"); 1972 return 1; 1973 } 1974 1975 return -1; 1976 } 1977 1978 int main(int argc, char *argv[]) 1979 { 1980 srvr_sockaddr_union_t me; 1981 curl_socket_t sock = CURL_SOCKET_BAD; 1982 int wrotepidfile = 0; 1983 int flag; 1984 unsigned short port = DEFAULT_PORT; 1985 #ifdef USE_UNIX_SOCKETS 1986 const char *unix_socket = NULL; 1987 bool unlink_socket = false; 1988 #endif 1989 const char *pidname = ".http.pid"; 1990 struct httprequest req; 1991 int rc = 0; 1992 int error; 1993 int arg = 1; 1994 long pid; 1995 const char *connecthost = "127.0.0.1"; 1996 const char *socket_type = "IPv4"; 1997 char port_str[11]; 1998 const char *location_str = port_str; 1999 2000 /* a default CONNECT port is basically pointless but still ... */ 2001 size_t socket_idx; 2002 2003 memset(&req, 0, sizeof(req)); 2004 2005 while(argc>arg) { 2006 if(!strcmp("--version", argv[arg])) { 2007 puts("sws IPv4" 2008 #ifdef ENABLE_IPV6 2009 "/IPv6" 2010 #endif 2011 #ifdef USE_UNIX_SOCKETS 2012 "/unix" 2013 #endif 2014 ); 2015 return 0; 2016 } 2017 else if(!strcmp("--pidfile", argv[arg])) { 2018 arg++; 2019 if(argc>arg) 2020 pidname = argv[arg++]; 2021 } 2022 else if(!strcmp("--logfile", argv[arg])) { 2023 arg++; 2024 if(argc>arg) 2025 serverlogfile = argv[arg++]; 2026 } 2027 else if(!strcmp("--gopher", argv[arg])) { 2028 arg++; 2029 use_gopher = TRUE; 2030 end_of_headers = "\r\n"; /* gopher style is much simpler */ 2031 } 2032 else if(!strcmp("--ipv4", argv[arg])) { 2033 socket_type = "IPv4"; 2034 socket_domain = AF_INET; 2035 location_str = port_str; 2036 arg++; 2037 } 2038 else if(!strcmp("--ipv6", argv[arg])) { 2039 #ifdef ENABLE_IPV6 2040 socket_type = "IPv6"; 2041 socket_domain = AF_INET6; 2042 location_str = port_str; 2043 #endif 2044 arg++; 2045 } 2046 else if(!strcmp("--unix-socket", argv[arg])) { 2047 arg++; 2048 if(argc>arg) { 2049 #ifdef USE_UNIX_SOCKETS 2050 unix_socket = argv[arg]; 2051 if(strlen(unix_socket) >= sizeof(me.sau.sun_path)) { 2052 fprintf(stderr, "sws: socket path must be shorter than %zu chars\n", 2053 sizeof(me.sau.sun_path)); 2054 return 0; 2055 } 2056 socket_type = "unix"; 2057 socket_domain = AF_UNIX; 2058 location_str = unix_socket; 2059 #endif 2060 arg++; 2061 } 2062 } 2063 else if(!strcmp("--port", argv[arg])) { 2064 arg++; 2065 if(argc>arg) { 2066 char *endptr; 2067 unsigned long ulnum = strtoul(argv[arg], &endptr, 10); 2068 if((endptr != argv[arg] + strlen(argv[arg])) || 2069 (ulnum < 1025UL) || (ulnum > 65535UL)) { 2070 fprintf(stderr, "sws: invalid --port argument (%s)\n", 2071 argv[arg]); 2072 return 0; 2073 } 2074 port = curlx_ultous(ulnum); 2075 arg++; 2076 } 2077 } 2078 else if(!strcmp("--srcdir", argv[arg])) { 2079 arg++; 2080 if(argc>arg) { 2081 path = argv[arg]; 2082 arg++; 2083 } 2084 } 2085 else if(!strcmp("--connect", argv[arg])) { 2086 /* The connect host IP number that the proxy will connect to no matter 2087 what the client asks for, but also use this as a hint that we run as 2088 a proxy and do a few different internal choices */ 2089 arg++; 2090 if(argc>arg) { 2091 connecthost = argv[arg]; 2092 arg++; 2093 is_proxy = TRUE; 2094 logmsg("Run as proxy, CONNECT to host %s", connecthost); 2095 } 2096 } 2097 else { 2098 puts("Usage: sws [option]\n" 2099 " --version\n" 2100 " --logfile [file]\n" 2101 " --pidfile [file]\n" 2102 " --ipv4\n" 2103 " --ipv6\n" 2104 " --unix-socket [file]\n" 2105 " --port [port]\n" 2106 " --srcdir [path]\n" 2107 " --connect [ip4-addr]\n" 2108 " --gopher"); 2109 return 0; 2110 } 2111 } 2112 2113 snprintf(port_str, sizeof(port_str), "port %hu", port); 2114 2115 #ifdef WIN32 2116 win32_init(); 2117 atexit(win32_cleanup); 2118 #endif 2119 2120 install_signal_handlers(); 2121 2122 pid = (long)getpid(); 2123 2124 sock = socket(socket_domain, SOCK_STREAM, 0); 2125 2126 all_sockets[0] = sock; 2127 num_sockets = 1; 2128 2129 if(CURL_SOCKET_BAD == sock) { 2130 error = SOCKERRNO; 2131 logmsg("Error creating socket: (%d) %s", 2132 error, strerror(error)); 2133 goto sws_cleanup; 2134 } 2135 2136 flag = 1; 2137 if(0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 2138 (void *)&flag, sizeof(flag))) { 2139 error = SOCKERRNO; 2140 logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s", 2141 error, strerror(error)); 2142 goto sws_cleanup; 2143 } 2144 if(0 != curlx_nonblock(sock, TRUE)) { 2145 error = SOCKERRNO; 2146 logmsg("curlx_nonblock failed with error: (%d) %s", 2147 error, strerror(error)); 2148 goto sws_cleanup; 2149 } 2150 2151 switch(socket_domain) { 2152 case AF_INET: 2153 memset(&me.sa4, 0, sizeof(me.sa4)); 2154 me.sa4.sin_family = AF_INET; 2155 me.sa4.sin_addr.s_addr = INADDR_ANY; 2156 me.sa4.sin_port = htons(port); 2157 rc = bind(sock, &me.sa, sizeof(me.sa4)); 2158 break; 2159 #ifdef ENABLE_IPV6 2160 case AF_INET6: 2161 memset(&me.sa6, 0, sizeof(me.sa6)); 2162 me.sa6.sin6_family = AF_INET6; 2163 me.sa6.sin6_addr = in6addr_any; 2164 me.sa6.sin6_port = htons(port); 2165 rc = bind(sock, &me.sa, sizeof(me.sa6)); 2166 break; 2167 #endif /* ENABLE_IPV6 */ 2168 #ifdef USE_UNIX_SOCKETS 2169 case AF_UNIX: 2170 memset(&me.sau, 0, sizeof(me.sau)); 2171 me.sau.sun_family = AF_UNIX; 2172 strncpy(me.sau.sun_path, unix_socket, sizeof(me.sau.sun_path)); 2173 rc = bind(sock, &me.sa, sizeof(me.sau)); 2174 if(0 != rc && errno == EADDRINUSE) { 2175 struct stat statbuf; 2176 /* socket already exists. Perhaps it is stale? */ 2177 int unixfd = socket(AF_UNIX, SOCK_STREAM, 0); 2178 if(CURL_SOCKET_BAD == unixfd) { 2179 error = SOCKERRNO; 2180 logmsg("Error binding socket, failed to create socket at %s: (%d) %s", 2181 unix_socket, error, strerror(error)); 2182 goto sws_cleanup; 2183 } 2184 /* check whether the server is alive */ 2185 rc = connect(unixfd, &me.sa, sizeof(me.sau)); 2186 error = errno; 2187 close(unixfd); 2188 if(ECONNREFUSED != error) { 2189 logmsg("Error binding socket, failed to connect to %s: (%d) %s", 2190 unix_socket, error, strerror(error)); 2191 goto sws_cleanup; 2192 } 2193 /* socket server is not alive, now check if it was actually a socket. 2194 * Systems which have Unix sockets will also have lstat */ 2195 rc = lstat(unix_socket, &statbuf); 2196 if(0 != rc) { 2197 logmsg("Error binding socket, failed to stat %s: (%d) %s", 2198 unix_socket, errno, strerror(errno)); 2199 goto sws_cleanup; 2200 } 2201 if((statbuf.st_mode & S_IFSOCK) != S_IFSOCK) { 2202 logmsg("Error binding socket, failed to stat %s: (%d) %s", 2203 unix_socket, error, strerror(error)); 2204 goto sws_cleanup; 2205 } 2206 /* dead socket, cleanup and retry bind */ 2207 rc = unlink(unix_socket); 2208 if(0 != rc) { 2209 logmsg("Error binding socket, failed to unlink %s: (%d) %s", 2210 unix_socket, errno, strerror(errno)); 2211 goto sws_cleanup; 2212 } 2213 /* stale socket is gone, retry bind */ 2214 rc = bind(sock, &me.sa, sizeof(me.sau)); 2215 } 2216 break; 2217 #endif /* USE_UNIX_SOCKETS */ 2218 } 2219 if(0 != rc) { 2220 error = SOCKERRNO; 2221 logmsg("Error binding socket on %s: (%d) %s", 2222 location_str, error, strerror(error)); 2223 goto sws_cleanup; 2224 } 2225 2226 logmsg("Running %s %s version on %s", 2227 use_gopher?"GOPHER":"HTTP", socket_type, location_str); 2228 2229 /* start accepting connections */ 2230 rc = listen(sock, 5); 2231 if(0 != rc) { 2232 error = SOCKERRNO; 2233 logmsg("listen() failed with error: (%d) %s", 2234 error, strerror(error)); 2235 goto sws_cleanup; 2236 } 2237 2238 #ifdef USE_UNIX_SOCKETS 2239 /* listen succeeds, so let's assume a valid listening Unix socket */ 2240 unlink_socket = true; 2241 #endif 2242 2243 /* 2244 ** As soon as this server writes its pid file the test harness will 2245 ** attempt to connect to this server and initiate its verification. 2246 */ 2247 2248 wrotepidfile = write_pidfile(pidname); 2249 if(!wrotepidfile) 2250 goto sws_cleanup; 2251 2252 /* initialization of httprequest struct is done before get_request(), but 2253 the pipelining struct field must be initialized previously to FALSE 2254 every time a new connection arrives. */ 2255 2256 req.pipelining = FALSE; 2257 init_httprequest(&req); 2258 2259 for(;;) { 2260 fd_set input; 2261 fd_set output; 2262 struct timeval timeout = {0, 250000L}; /* 250 ms */ 2263 curl_socket_t maxfd = (curl_socket_t)-1; 2264 2265 /* Clear out closed sockets */ 2266 for(socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) { 2267 if(CURL_SOCKET_BAD == all_sockets[socket_idx]) { 2268 char *dst = (char *) (all_sockets + socket_idx); 2269 char *src = (char *) (all_sockets + socket_idx + 1); 2270 char *end = (char *) (all_sockets + num_sockets); 2271 memmove(dst, src, end - src); 2272 num_sockets -= 1; 2273 } 2274 } 2275 2276 if(got_exit_signal) 2277 goto sws_cleanup; 2278 2279 /* Set up for select */ 2280 FD_ZERO(&input); 2281 FD_ZERO(&output); 2282 2283 for(socket_idx = 0; socket_idx < num_sockets; ++socket_idx) { 2284 /* Listen on all sockets */ 2285 FD_SET(all_sockets[socket_idx], &input); 2286 if(all_sockets[socket_idx] > maxfd) 2287 maxfd = all_sockets[socket_idx]; 2288 } 2289 2290 if(got_exit_signal) 2291 goto sws_cleanup; 2292 2293 rc = select((int)maxfd + 1, &input, &output, NULL, &timeout); 2294 if(rc < 0) { 2295 error = SOCKERRNO; 2296 logmsg("select() failed with error: (%d) %s", 2297 error, strerror(error)); 2298 goto sws_cleanup; 2299 } 2300 2301 if(got_exit_signal) 2302 goto sws_cleanup; 2303 2304 if(rc == 0) { 2305 /* Timed out - try again */ 2306 continue; 2307 } 2308 2309 /* Check if the listening socket is ready to accept */ 2310 if(FD_ISSET(all_sockets[0], &input)) { 2311 /* Service all queued connections */ 2312 curl_socket_t msgsock; 2313 do { 2314 msgsock = accept_connection(sock); 2315 logmsg("accept_connection %d returned %d", sock, msgsock); 2316 if(CURL_SOCKET_BAD == msgsock) 2317 goto sws_cleanup; 2318 } while(msgsock > 0); 2319 } 2320 2321 /* Service all connections that are ready */ 2322 for(socket_idx = 1; socket_idx < num_sockets; ++socket_idx) { 2323 if(FD_ISSET(all_sockets[socket_idx], &input)) { 2324 if(got_exit_signal) 2325 goto sws_cleanup; 2326 2327 /* Service this connection until it has nothing available */ 2328 do { 2329 rc = service_connection(all_sockets[socket_idx], &req, sock, 2330 connecthost); 2331 if(got_exit_signal) 2332 goto sws_cleanup; 2333 2334 if(rc < 0) { 2335 logmsg("====> Client disconnect %d", req.connmon); 2336 2337 if(req.connmon) { 2338 const char *keepopen = "[DISCONNECT]\n"; 2339 storerequest(keepopen, strlen(keepopen)); 2340 } 2341 2342 if(!req.open) 2343 /* When instructed to close connection after server-reply we 2344 wait a very small amount of time before doing so. If this 2345 is not done client might get an ECONNRESET before reading 2346 a single byte of server-reply. */ 2347 wait_ms(50); 2348 2349 if(all_sockets[socket_idx] != CURL_SOCKET_BAD) { 2350 sclose(all_sockets[socket_idx]); 2351 all_sockets[socket_idx] = CURL_SOCKET_BAD; 2352 } 2353 2354 serverlogslocked -= 1; 2355 if(!serverlogslocked) 2356 clear_advisor_read_lock(SERVERLOGS_LOCK); 2357 2358 if(req.testno == DOCNUMBER_QUIT) 2359 goto sws_cleanup; 2360 } 2361 2362 /* Reset the request, unless we're still in the middle of reading */ 2363 if(rc != 0) 2364 init_httprequest(&req); 2365 } while(rc > 0); 2366 } 2367 } 2368 2369 if(got_exit_signal) 2370 goto sws_cleanup; 2371 } 2372 2373 sws_cleanup: 2374 2375 for(socket_idx = 1; socket_idx < num_sockets; ++socket_idx) 2376 if((all_sockets[socket_idx] != sock) && 2377 (all_sockets[socket_idx] != CURL_SOCKET_BAD)) 2378 sclose(all_sockets[socket_idx]); 2379 2380 if(sock != CURL_SOCKET_BAD) 2381 sclose(sock); 2382 2383 #ifdef USE_UNIX_SOCKETS 2384 if(unlink_socket && socket_domain == AF_UNIX) { 2385 rc = unlink(unix_socket); 2386 logmsg("unlink(%s) = %d (%s)", unix_socket, rc, strerror(rc)); 2387 } 2388 #endif 2389 2390 if(got_exit_signal) 2391 logmsg("signalled to die"); 2392 2393 if(wrotepidfile) 2394 unlink(pidname); 2395 2396 if(serverlogslocked) { 2397 serverlogslocked = 0; 2398 clear_advisor_read_lock(SERVERLOGS_LOCK); 2399 } 2400 2401 restore_signal_handlers(); 2402 2403 if(got_exit_signal) { 2404 logmsg("========> %s sws (%s pid: %ld) exits with signal (%d)", 2405 socket_type, location_str, pid, exit_signal); 2406 /* 2407 * To properly set the return status of the process we 2408 * must raise the same signal SIGINT or SIGTERM that we 2409 * caught and let the old handler take care of it. 2410 */ 2411 raise(exit_signal); 2412 } 2413 2414 logmsg("========> sws quits"); 2415 return 0; 2416 } 2417 2418