00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "server_setup.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifdef HAVE_SIGNAL_H
00032 #include <signal.h>
00033 #endif
00034 #ifdef HAVE_NETINET_IN_H
00035 #include <netinet/in.h>
00036 #endif
00037 #ifdef HAVE_ARPA_INET_H
00038 #include <arpa/inet.h>
00039 #endif
00040 #ifdef HAVE_NETDB_H
00041 #include <netdb.h>
00042 #endif
00043 #ifdef HAVE_NETINET_TCP_H
00044 #include <netinet/tcp.h>
00045 #endif
00046
00047 #define ENABLE_CURLX_PRINTF
00048
00049
00050 #include "curlx.h"
00051 #include "getpart.h"
00052 #include "inet_pton.h"
00053 #include "util.h"
00054 #include "server_sockaddr.h"
00055
00056
00057 #include "memdebug.h"
00058
00059 #ifdef USE_WINSOCK
00060 #undef EINTR
00061 #define EINTR 4
00062 #undef EAGAIN
00063 #define EAGAIN 11
00064 #undef ERANGE
00065 #define ERANGE 34
00066 #endif
00067
00068 static enum {
00069 socket_domain_inet = AF_INET
00070 #ifdef ENABLE_IPV6
00071 , socket_domain_inet6 = AF_INET6
00072 #endif
00073 #ifdef USE_UNIX_SOCKETS
00074 , socket_domain_unix = AF_UNIX
00075 #endif
00076 } socket_domain = AF_INET;
00077 static bool use_gopher = FALSE;
00078 static int serverlogslocked = 0;
00079 static bool is_proxy = FALSE;
00080
00081 #define REQBUFSIZ 150000
00082 #define REQBUFSIZ_TXT "149999"
00083
00084 static long prevtestno=-1;
00085 static long prevpartno=-1;
00086 static bool prevbounce=FALSE;
00087
00088
00089
00090 #define RCMD_NORMALREQ 0
00091 #define RCMD_IDLE 1
00092 #define RCMD_STREAM 2
00093
00094 struct httprequest {
00095 char reqbuf[REQBUFSIZ];
00096 bool connect_request;
00097 unsigned short connect_port;
00098 size_t checkindex;
00099 size_t offset;
00100 long testno;
00101 long partno;
00102 bool open;
00103 bool auth_req;
00104
00105 bool auth;
00106 size_t cl;
00107 bool digest;
00108 bool ntlm;
00109 int writedelay;
00110
00111 int pipe;
00112
00113 int skip;
00114
00115
00116
00117 int rcmd;
00118 int prot_version;
00119 bool pipelining;
00120 int callcount;
00121 bool connmon;
00122 bool upgrade;
00123 bool upgrade_request;
00124 int done_processing;
00125 };
00126
00127 #define MAX_SOCKETS 1024
00128
00129 static curl_socket_t all_sockets[MAX_SOCKETS];
00130 static size_t num_sockets = 0;
00131
00132 static int ProcessRequest(struct httprequest *req);
00133 static void storerequest(char *reqbuf, size_t totalsize);
00134
00135 #define DEFAULT_PORT 8999
00136
00137 #ifndef DEFAULT_LOGFILE
00138 #define DEFAULT_LOGFILE "log/sws.log"
00139 #endif
00140
00141 const char *serverlogfile = DEFAULT_LOGFILE;
00142
00143 #define SWSVERSION "curl test suite HTTP server/0.1"
00144
00145 #define REQUEST_DUMP "log/server.input"
00146 #define RESPONSE_DUMP "log/server.response"
00147
00148
00149
00150 #define REQUEST_PROXY_DUMP "log/proxy.input"
00151 #define RESPONSE_PROXY_DUMP "log/proxy.response"
00152
00153
00154 #define MAXDOCNAMELEN 140000
00155 #define MAXDOCNAMELEN_TXT "139999"
00156
00157 #define REQUEST_KEYWORD_SIZE 256
00158 #define REQUEST_KEYWORD_SIZE_TXT "255"
00159
00160 #define CMD_AUTH_REQUIRED "auth_required"
00161
00162
00163
00164 #define CMD_IDLE "idle"
00165
00166
00167 #define CMD_STREAM "stream"
00168
00169
00170
00171
00172 #define CMD_CONNECTIONMONITOR "connection-monitor"
00173
00174
00175 #define CMD_UPGRADE "upgrade"
00176
00177 #define END_OF_HEADERS "\r\n\r\n"
00178
00179 enum {
00180 DOCNUMBER_NOTHING = -4,
00181 DOCNUMBER_QUIT = -3,
00182 DOCNUMBER_WERULEZ = -2,
00183 DOCNUMBER_404 = -1
00184 };
00185
00186 static const char *end_of_headers = END_OF_HEADERS;
00187
00188
00189 static const char *docquit =
00190 "HTTP/1.1 200 Goodbye" END_OF_HEADERS;
00191
00192
00193 static const char *doc404 = "HTTP/1.1 404 Not Found\r\n"
00194 "Server: " SWSVERSION "\r\n"
00195 "Connection: close\r\n"
00196 "Content-Type: text/html"
00197 END_OF_HEADERS
00198 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
00199 "<HTML><HEAD>\n"
00200 "<TITLE>404 Not Found</TITLE>\n"
00201 "</HEAD><BODY>\n"
00202 "<H1>Not Found</H1>\n"
00203 "The requested URL was not found on this server.\n"
00204 "<P><HR><ADDRESS>" SWSVERSION "</ADDRESS>\n" "</BODY></HTML>\n";
00205
00206
00207
00208 #ifndef HAVE_SIGINTERRUPT
00209 #define siginterrupt(x,y) do {} while(0)
00210 #endif
00211
00212
00213
00214 typedef RETSIGTYPE (*SIGHANDLER_T)(int);
00215
00216 #ifdef SIGHUP
00217 static SIGHANDLER_T old_sighup_handler = SIG_ERR;
00218 #endif
00219
00220 #ifdef SIGPIPE
00221 static SIGHANDLER_T old_sigpipe_handler = SIG_ERR;
00222 #endif
00223
00224 #ifdef SIGALRM
00225 static SIGHANDLER_T old_sigalrm_handler = SIG_ERR;
00226 #endif
00227
00228 #ifdef SIGINT
00229 static SIGHANDLER_T old_sigint_handler = SIG_ERR;
00230 #endif
00231
00232 #ifdef SIGTERM
00233 static SIGHANDLER_T old_sigterm_handler = SIG_ERR;
00234 #endif
00235
00236 #if defined(SIGBREAK) && defined(WIN32)
00237 static SIGHANDLER_T old_sigbreak_handler = SIG_ERR;
00238 #endif
00239
00240
00241
00242 SIG_ATOMIC_T got_exit_signal = 0;
00243
00244
00245
00246 static volatile int exit_signal = 0;
00247
00248
00249
00250
00251
00252
00253 static RETSIGTYPE exit_signal_handler(int signum)
00254 {
00255 int old_errno = errno;
00256 if(got_exit_signal == 0) {
00257 got_exit_signal = 1;
00258 exit_signal = signum;
00259 }
00260 (void)signal(signum, exit_signal_handler);
00261 errno = old_errno;
00262 }
00263
00264 static void install_signal_handlers(void)
00265 {
00266 #ifdef SIGHUP
00267
00268 old_sighup_handler = signal(SIGHUP, SIG_IGN);
00269 if(old_sighup_handler == SIG_ERR)
00270 logmsg("cannot install SIGHUP handler: %s", strerror(errno));
00271 #endif
00272 #ifdef SIGPIPE
00273
00274 old_sigpipe_handler = signal(SIGPIPE, SIG_IGN);
00275 if(old_sigpipe_handler == SIG_ERR)
00276 logmsg("cannot install SIGPIPE handler: %s", strerror(errno));
00277 #endif
00278 #ifdef SIGALRM
00279
00280 old_sigalrm_handler = signal(SIGALRM, SIG_IGN);
00281 if(old_sigalrm_handler == SIG_ERR)
00282 logmsg("cannot install SIGALRM handler: %s", strerror(errno));
00283 #endif
00284 #ifdef SIGINT
00285
00286 old_sigint_handler = signal(SIGINT, exit_signal_handler);
00287 if(old_sigint_handler == SIG_ERR)
00288 logmsg("cannot install SIGINT handler: %s", strerror(errno));
00289 else
00290 siginterrupt(SIGINT, 1);
00291 #endif
00292 #ifdef SIGTERM
00293
00294 old_sigterm_handler = signal(SIGTERM, exit_signal_handler);
00295 if(old_sigterm_handler == SIG_ERR)
00296 logmsg("cannot install SIGTERM handler: %s", strerror(errno));
00297 else
00298 siginterrupt(SIGTERM, 1);
00299 #endif
00300 #if defined(SIGBREAK) && defined(WIN32)
00301
00302 old_sigbreak_handler = signal(SIGBREAK, exit_signal_handler);
00303 if(old_sigbreak_handler == SIG_ERR)
00304 logmsg("cannot install SIGBREAK handler: %s", strerror(errno));
00305 else
00306 siginterrupt(SIGBREAK, 1);
00307 #endif
00308 }
00309
00310 static void restore_signal_handlers(void)
00311 {
00312 #ifdef SIGHUP
00313 if(SIG_ERR != old_sighup_handler)
00314 (void)signal(SIGHUP, old_sighup_handler);
00315 #endif
00316 #ifdef SIGPIPE
00317 if(SIG_ERR != old_sigpipe_handler)
00318 (void)signal(SIGPIPE, old_sigpipe_handler);
00319 #endif
00320 #ifdef SIGALRM
00321 if(SIG_ERR != old_sigalrm_handler)
00322 (void)signal(SIGALRM, old_sigalrm_handler);
00323 #endif
00324 #ifdef SIGINT
00325 if(SIG_ERR != old_sigint_handler)
00326 (void)signal(SIGINT, old_sigint_handler);
00327 #endif
00328 #ifdef SIGTERM
00329 if(SIG_ERR != old_sigterm_handler)
00330 (void)signal(SIGTERM, old_sigterm_handler);
00331 #endif
00332 #if defined(SIGBREAK) && defined(WIN32)
00333 if(SIG_ERR != old_sigbreak_handler)
00334 (void)signal(SIGBREAK, old_sigbreak_handler);
00335 #endif
00336 }
00337
00338
00339 static bool socket_domain_is_ip(void)
00340 {
00341 switch(socket_domain) {
00342 case AF_INET:
00343 #ifdef ENABLE_IPV6
00344 case AF_INET6:
00345 #endif
00346 return true;
00347 default:
00348
00349 return false;
00350 }
00351 }
00352
00353
00354 static int parse_servercmd(struct httprequest *req)
00355 {
00356 FILE *stream;
00357 char *filename;
00358 int error;
00359
00360 filename = test2file(req->testno);
00361
00362 stream=fopen(filename, "rb");
00363 if(!stream) {
00364 error = errno;
00365 logmsg("fopen() failed with error: %d %s", error, strerror(error));
00366 logmsg(" [1] Error opening file: %s", filename);
00367 logmsg(" Couldn't open test file %ld", req->testno);
00368 req->open = FALSE;
00369 return 1;
00370 }
00371 else {
00372 char *orgcmd = NULL;
00373 char *cmd = NULL;
00374 size_t cmdsize = 0;
00375 int num=0;
00376
00377
00378 error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream);
00379 fclose(stream);
00380 if(error) {
00381 logmsg("getpart() failed with error: %d", error);
00382 req->open = FALSE;
00383 return 1;
00384 }
00385
00386 req->connmon = FALSE;
00387
00388 cmd = orgcmd;
00389 while(cmd && cmdsize) {
00390 char *check;
00391
00392 if(!strncmp(CMD_AUTH_REQUIRED, cmd, strlen(CMD_AUTH_REQUIRED))) {
00393 logmsg("instructed to require authorization header");
00394 req->auth_req = TRUE;
00395 }
00396 else if(!strncmp(CMD_IDLE, cmd, strlen(CMD_IDLE))) {
00397 logmsg("instructed to idle");
00398 req->rcmd = RCMD_IDLE;
00399 req->open = TRUE;
00400 }
00401 else if(!strncmp(CMD_STREAM, cmd, strlen(CMD_STREAM))) {
00402 logmsg("instructed to stream");
00403 req->rcmd = RCMD_STREAM;
00404 }
00405 else if(!strncmp(CMD_CONNECTIONMONITOR, cmd,
00406 strlen(CMD_CONNECTIONMONITOR))) {
00407 logmsg("enabled connection monitoring");
00408 req->connmon = TRUE;
00409 }
00410 else if(!strncmp(CMD_UPGRADE, cmd, strlen(CMD_UPGRADE))) {
00411 logmsg("enabled upgrade to http2");
00412 req->upgrade = TRUE;
00413 }
00414 else if(1 == sscanf(cmd, "pipe: %d", &num)) {
00415 logmsg("instructed to allow a pipe size of %d", num);
00416 if(num < 0)
00417 logmsg("negative pipe size ignored");
00418 else if(num > 0)
00419 req->pipe = num-1;
00420
00421 }
00422 else if(1 == sscanf(cmd, "skip: %d", &num)) {
00423 logmsg("instructed to skip this number of bytes %d", num);
00424 req->skip = num;
00425 }
00426 else if(1 == sscanf(cmd, "writedelay: %d", &num)) {
00427 logmsg("instructed to delay %d secs between packets", num);
00428 req->writedelay = num;
00429 }
00430 else {
00431 logmsg("Unknown <servercmd> instruction found: %s", cmd);
00432 }
00433
00434 check = strchr(cmd, '\r');
00435 if(!check)
00436 check = strchr(cmd, '\n');
00437
00438 if(check) {
00439
00440 while((*check == '\r') || (*check == '\n'))
00441 check++;
00442
00443 if(!*check)
00444
00445 break;
00446 cmd = check;
00447 }
00448 else
00449 break;
00450 }
00451 free(orgcmd);
00452 }
00453
00454 return 0;
00455 }
00456
00457 static int ProcessRequest(struct httprequest *req)
00458 {
00459 char *line=&req->reqbuf[req->checkindex];
00460 bool chunked = FALSE;
00461 static char request[REQUEST_KEYWORD_SIZE];
00462 static char doc[MAXDOCNAMELEN];
00463 char logbuf[456];
00464 int prot_major, prot_minor;
00465 char *end = strstr(line, end_of_headers);
00466
00467 req->callcount++;
00468
00469 logmsg("Process %d bytes request%s", req->offset,
00470 req->callcount > 1?" [CONTINUED]":"");
00471
00472
00473
00474
00475 if(use_gopher &&
00476 (req->testno == DOCNUMBER_NOTHING) &&
00477 !strncmp("/verifiedserver", line, 15)) {
00478 logmsg("Are-we-friendly question received");
00479 req->testno = DOCNUMBER_WERULEZ;
00480 return 1;
00481 }
00482
00483 else if((req->testno == DOCNUMBER_NOTHING) &&
00484 sscanf(line,
00485 "%" REQUEST_KEYWORD_SIZE_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
00486 request,
00487 doc,
00488 &prot_major,
00489 &prot_minor) == 4) {
00490 char *ptr;
00491
00492 req->prot_version = prot_major*10 + prot_minor;
00493
00494
00495 ptr = strrchr(doc, '/');
00496
00497
00498 if(ptr) {
00499 if((strlen(doc) + strlen(request)) < 400)
00500 snprintf(logbuf, sizeof(logbuf), "Got request: %s %s HTTP/%d.%d",
00501 request, doc, prot_major, prot_minor);
00502 else
00503 snprintf(logbuf, sizeof(logbuf), "Got a *HUGE* request HTTP/%d.%d",
00504 prot_major, prot_minor);
00505 logmsg("%s", logbuf);
00506
00507 if(!strncmp("/verifiedserver", ptr, 15)) {
00508 logmsg("Are-we-friendly question received");
00509 req->testno = DOCNUMBER_WERULEZ;
00510 return 1;
00511 }
00512
00513 if(!strncmp("/quit", ptr, 5)) {
00514 logmsg("Request-to-quit received");
00515 req->testno = DOCNUMBER_QUIT;
00516 return 1;
00517 }
00518
00519 ptr++;
00520
00521
00522 while(*ptr && !ISDIGIT(*ptr))
00523 ptr++;
00524
00525 req->testno = strtol(ptr, &ptr, 10);
00526
00527 if(req->testno > 10000) {
00528 req->partno = req->testno % 10000;
00529 req->testno /= 10000;
00530 }
00531 else
00532 req->partno = 0;
00533
00534 if(req->testno) {
00535
00536 snprintf(logbuf, sizeof(logbuf), "Requested test number %ld part %ld",
00537 req->testno, req->partno);
00538 logmsg("%s", logbuf);
00539
00540
00541 parse_servercmd(req);
00542 }
00543 else
00544 req->testno = DOCNUMBER_NOTHING;
00545
00546 }
00547
00548 if(req->testno == DOCNUMBER_NOTHING) {
00549
00550
00551
00552 if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
00553 doc, &prot_major, &prot_minor) == 3) {
00554 char *portp = NULL;
00555 unsigned long part=0;
00556
00557 snprintf(logbuf, sizeof(logbuf),
00558 "Received a CONNECT %s HTTP/%d.%d request",
00559 doc, prot_major, prot_minor);
00560 logmsg("%s", logbuf);
00561
00562 req->connect_request = TRUE;
00563
00564 if(req->prot_version == 10)
00565 req->open = FALSE;
00566
00567 if(doc[0] == '[') {
00568 char *p = &doc[1];
00569
00570
00571 while(*p && (ISXDIGIT(*p) || (*p == ':') || (*p == '.'))) {
00572 char *endp;
00573 part = strtoul(p, &endp, 16);
00574 if(ISXDIGIT(*p))
00575 p = endp;
00576 else
00577 p++;
00578 }
00579 if(*p != ']')
00580 logmsg("Invalid CONNECT IPv6 address format");
00581 else if(*(p+1) != ':')
00582 logmsg("Invalid CONNECT IPv6 port format");
00583 else
00584 portp = p+1;
00585
00586 req->testno = part;
00587 }
00588 else
00589 portp = strchr(doc, ':');
00590
00591 if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1))) {
00592 unsigned long ulnum = strtoul(portp+1, NULL, 10);
00593 if(!ulnum || (ulnum > 65535UL))
00594 logmsg("Invalid CONNECT port received");
00595 else
00596 req->connect_port = curlx_ultous(ulnum);
00597
00598 }
00599 logmsg("Port number: %d, test case number: %ld",
00600 req->connect_port, req->testno);
00601 }
00602 }
00603
00604 if(req->testno == DOCNUMBER_NOTHING) {
00605
00606
00607
00608
00609
00610 ptr = strrchr(doc, '.');
00611
00612
00613 if(ptr) {
00614 ptr++;
00615
00616 req->testno = strtol(ptr, &ptr, 10);
00617
00618 if(req->testno > 10000) {
00619 req->partno = req->testno % 10000;
00620 req->testno /= 10000;
00621
00622 logmsg("found test %d in requested host name", req->testno);
00623
00624 }
00625 else
00626 req->partno = 0;
00627
00628 snprintf(logbuf, sizeof(logbuf),
00629 "Requested test number %ld part %ld (from host name)",
00630 req->testno, req->partno);
00631 logmsg("%s", logbuf);
00632
00633 }
00634
00635 if(!req->testno) {
00636 logmsg("Did not find test number in PATH");
00637 req->testno = DOCNUMBER_404;
00638 }
00639 else
00640 parse_servercmd(req);
00641 }
00642 }
00643 else if((req->offset >= 3) && (req->testno == DOCNUMBER_NOTHING)) {
00644 logmsg("** Unusual request. Starts with %02x %02x %02x",
00645 line[0], line[1], line[2]);
00646 }
00647
00648 if(!end) {
00649
00650 logmsg("request not complete yet");
00651 return 0;
00652 }
00653 logmsg("- request found to be complete");
00654
00655 if(use_gopher) {
00656
00657
00658 char *ptr;
00659
00660
00661 ptr = strrchr(line, '/');
00662
00663 if(ptr) {
00664 ptr++;
00665
00666
00667 while(*ptr && !ISDIGIT(*ptr))
00668 ptr++;
00669
00670 req->testno = strtol(ptr, &ptr, 10);
00671
00672 if(req->testno > 10000) {
00673 req->partno = req->testno % 10000;
00674 req->testno /= 10000;
00675 }
00676 else
00677 req->partno = 0;
00678
00679 snprintf(logbuf, sizeof(logbuf),
00680 "Requested GOPHER test number %ld part %ld",
00681 req->testno, req->partno);
00682 logmsg("%s", logbuf);
00683 }
00684 }
00685
00686 if(req->pipe)
00687
00688
00689 req->checkindex += (end - line) + strlen(end_of_headers);
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 do {
00703 if(got_exit_signal)
00704 return 1;
00705
00706 if((req->cl==0) && strncasecompare("Content-Length:", line, 15)) {
00707
00708
00709
00710
00711 char *endptr;
00712 char *ptr = line + 15;
00713 unsigned long clen = 0;
00714 while(*ptr && ISSPACE(*ptr))
00715 ptr++;
00716 endptr = ptr;
00717 errno = 0;
00718 clen = strtoul(ptr, &endptr, 10);
00719 if((ptr == endptr) || !ISSPACE(*endptr) || (ERANGE == errno)) {
00720
00721 logmsg("Found invalid Content-Length: (%s) in the request", ptr);
00722 req->open = FALSE;
00723 return 1;
00724 }
00725 req->cl = clen - req->skip;
00726
00727 logmsg("Found Content-Length: %lu in the request", clen);
00728 if(req->skip)
00729 logmsg("... but will abort after %zu bytes", req->cl);
00730 break;
00731 }
00732 else if(strncasecompare("Transfer-Encoding: chunked", line,
00733 strlen("Transfer-Encoding: chunked"))) {
00734
00735 chunked = TRUE;
00736 }
00737
00738 if(chunked) {
00739 if(strstr(req->reqbuf, "\r\n0\r\n\r\n"))
00740
00741 return 1;
00742 else
00743 return 0;
00744 }
00745
00746 line = strchr(line, '\n');
00747 if(line)
00748 line++;
00749
00750 } while(line);
00751
00752 if(!req->auth && strstr(req->reqbuf, "Authorization:")) {
00753 req->auth = TRUE;
00754 if(req->auth_req)
00755 logmsg("Authorization header found, as required");
00756 }
00757
00758 if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
00759
00760
00761
00762 req->partno += 1000;
00763 req->digest = TRUE;
00764 logmsg("Received Digest request, sending back data %ld", req->partno);
00765 }
00766 else if(!req->ntlm &&
00767 strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) {
00768
00769 req->partno += 1002;
00770 req->ntlm = TRUE;
00771 logmsg("Received NTLM type-3, sending back data %ld", req->partno);
00772 if(req->cl) {
00773 logmsg(" Expecting %zu POSTed bytes", req->cl);
00774 }
00775 }
00776 else if(!req->ntlm &&
00777 strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) {
00778
00779 req->partno += 1001;
00780 req->ntlm = TRUE;
00781 logmsg("Received NTLM type-1, sending back data %ld", req->partno);
00782 }
00783 else if((req->partno >= 1000) &&
00784 strstr(req->reqbuf, "Authorization: Basic")) {
00785
00786
00787
00788 req->partno += 1;
00789 logmsg("Received Basic request, sending back data %ld", req->partno);
00790 }
00791 if(strstr(req->reqbuf, "Connection: close"))
00792 req->open = FALSE;
00793
00794 if(!req->pipe &&
00795 req->open &&
00796 req->prot_version >= 11 &&
00797 end &&
00798 req->reqbuf + req->offset > end + strlen(end_of_headers) &&
00799 !req->cl &&
00800 (!strncmp(req->reqbuf, "GET", strlen("GET")) ||
00801 !strncmp(req->reqbuf, "HEAD", strlen("HEAD")))) {
00802
00803
00804 req->checkindex = (end - req->reqbuf) + strlen(end_of_headers);
00805 req->pipelining = TRUE;
00806 }
00807
00808 while(req->pipe) {
00809 if(got_exit_signal)
00810 return 1;
00811
00812 line = &req->reqbuf[req->checkindex];
00813 end = strstr(line, end_of_headers);
00814 if(!end)
00815 break;
00816 req->checkindex += (end - line) + strlen(end_of_headers);
00817 req->pipe--;
00818 }
00819
00820
00821
00822
00823
00824 if(req->auth_req && !req->auth) {
00825 logmsg("Return early due to auth requested by none provided");
00826 return 1;
00827 }
00828
00829 if(req->upgrade && strstr(req->reqbuf, "Upgrade:")) {
00830
00831 logmsg("Found Upgrade: in request and allows it");
00832 req->upgrade_request = TRUE;
00833 }
00834
00835 if(req->cl > 0) {
00836 if(req->cl <= req->offset - (end - req->reqbuf) - strlen(end_of_headers))
00837 return 1;
00838 else
00839 return 0;
00840 }
00841
00842 return 1;
00843 }
00844
00845
00846 static void storerequest(char *reqbuf, size_t totalsize)
00847 {
00848 int res;
00849 int error = 0;
00850 size_t written;
00851 size_t writeleft;
00852 FILE *dump;
00853 const char *dumpfile=is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP;
00854
00855 if(reqbuf == NULL)
00856 return;
00857 if(totalsize == 0)
00858 return;
00859
00860 do {
00861 dump = fopen(dumpfile, "ab");
00862 } while((dump == NULL) && ((error = errno) == EINTR));
00863 if(dump == NULL) {
00864 logmsg("[2] Error opening file %s error: %d %s",
00865 dumpfile, error, strerror(error));
00866 logmsg("Failed to write request input ");
00867 return;
00868 }
00869
00870 writeleft = totalsize;
00871 do {
00872 written = fwrite(&reqbuf[totalsize-writeleft],
00873 1, writeleft, dump);
00874 if(got_exit_signal)
00875 goto storerequest_cleanup;
00876 if(written > 0)
00877 writeleft -= written;
00878 } while((writeleft > 0) && ((error = errno) == EINTR));
00879
00880 if(writeleft == 0)
00881 logmsg("Wrote request (%zu bytes) input to %s", totalsize, dumpfile);
00882 else if(writeleft > 0) {
00883 logmsg("Error writing file %s error: %d %s",
00884 dumpfile, error, strerror(error));
00885 logmsg("Wrote only (%zu bytes) of (%zu bytes) request input to %s",
00886 totalsize-writeleft, totalsize, dumpfile);
00887 }
00888
00889 storerequest_cleanup:
00890
00891 do {
00892 res = fclose(dump);
00893 } while(res && ((error = errno) == EINTR));
00894 if(res)
00895 logmsg("Error closing file %s error: %d %s",
00896 dumpfile, error, strerror(error));
00897 }
00898
00899 static void init_httprequest(struct httprequest *req)
00900 {
00901
00902
00903
00904 if(!req->pipelining) {
00905 req->checkindex = 0;
00906 req->offset = 0;
00907 }
00908 req->testno = DOCNUMBER_NOTHING;
00909 req->partno = 0;
00910 req->connect_request = FALSE;
00911 req->open = TRUE;
00912 req->auth_req = FALSE;
00913 req->auth = FALSE;
00914 req->cl = 0;
00915 req->digest = FALSE;
00916 req->ntlm = FALSE;
00917 req->pipe = 0;
00918 req->skip = 0;
00919 req->writedelay = 0;
00920 req->rcmd = RCMD_NORMALREQ;
00921 req->prot_version = 0;
00922 req->callcount = 0;
00923 req->connect_port = 0;
00924 req->done_processing = 0;
00925 req->upgrade = 0;
00926 req->upgrade_request = 0;
00927 }
00928
00929
00930
00931 static int get_request(curl_socket_t sock, struct httprequest *req)
00932 {
00933 int error;
00934 int fail = 0;
00935 char *reqbuf = req->reqbuf;
00936 ssize_t got = 0;
00937 int overflow = 0;
00938
00939 char *pipereq = NULL;
00940 size_t pipereq_length = 0;
00941
00942 if(req->pipelining) {
00943 pipereq = reqbuf + req->checkindex;
00944 pipereq_length = req->offset - req->checkindex;
00945
00946
00947
00948 req->pipelining = FALSE;
00949 req->checkindex = 0;
00950 req->offset = 0;
00951 }
00952
00953 if(req->offset >= REQBUFSIZ-1) {
00954
00955 overflow = 1;
00956 }
00957 else {
00958 if(pipereq_length && pipereq) {
00959 memmove(reqbuf, pipereq, pipereq_length);
00960 got = curlx_uztosz(pipereq_length);
00961 pipereq_length = 0;
00962 }
00963 else {
00964 if(req->skip)
00965
00966
00967
00968 got = sread(sock, reqbuf + req->offset, req->cl);
00969 else
00970 got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset);
00971 }
00972 if(got_exit_signal)
00973 return -1;
00974 if(got == 0) {
00975 logmsg("Connection closed by client");
00976 fail = 1;
00977 }
00978 else if(got < 0) {
00979 error = SOCKERRNO;
00980 if(EAGAIN == error || EWOULDBLOCK == error) {
00981
00982 return 0;
00983 }
00984 logmsg("recv() returned error: (%d) %s", error, strerror(error));
00985 fail = 1;
00986 }
00987 if(fail) {
00988
00989 reqbuf[req->offset] = '\0';
00990 storerequest(reqbuf, req->offset);
00991 return -1;
00992 }
00993
00994 logmsg("Read %zd bytes", got);
00995
00996 req->offset += (size_t)got;
00997 reqbuf[req->offset] = '\0';
00998
00999 req->done_processing = ProcessRequest(req);
01000 if(got_exit_signal)
01001 return -1;
01002 if(req->done_processing && req->pipe) {
01003 logmsg("Waiting for another piped request");
01004 req->done_processing = 0;
01005 req->pipe--;
01006 }
01007 }
01008
01009 if(overflow || (req->offset == REQBUFSIZ-1 && got > 0)) {
01010 logmsg("Request would overflow buffer, closing connection");
01011
01012 reqbuf[REQBUFSIZ-1] = '\0';
01013 fail = 1;
01014 }
01015 else if(req->offset > REQBUFSIZ-1) {
01016 logmsg("Request buffer overflow, closing connection");
01017
01018 reqbuf[REQBUFSIZ-1] = '\0';
01019 fail = 1;
01020 }
01021 else
01022 reqbuf[req->offset] = '\0';
01023
01024
01025 if(fail || req->done_processing)
01026 storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
01027 if(got_exit_signal)
01028 return -1;
01029
01030 return fail ? -1 : 1;
01031 }
01032
01033
01034 static int send_doc(curl_socket_t sock, struct httprequest *req)
01035 {
01036 ssize_t written;
01037 size_t count;
01038 const char *buffer;
01039 char *ptr=NULL;
01040 FILE *stream;
01041 char *cmd=NULL;
01042 size_t cmdsize=0;
01043 FILE *dump;
01044 bool persistant = TRUE;
01045 bool sendfailure = FALSE;
01046 size_t responsesize;
01047 int error = 0;
01048 int res;
01049 const char *responsedump = is_proxy?RESPONSE_PROXY_DUMP:RESPONSE_DUMP;
01050 static char weare[256];
01051
01052 switch(req->rcmd) {
01053 default:
01054 case RCMD_NORMALREQ:
01055 break;
01056 case RCMD_STREAM:
01057 #define STREAMTHIS "a string to stream 01234567890\n"
01058 count = strlen(STREAMTHIS);
01059 for(;;) {
01060 written = swrite(sock, STREAMTHIS, count);
01061 if(got_exit_signal)
01062 return -1;
01063 if(written != (ssize_t)count) {
01064 logmsg("Stopped streaming");
01065 break;
01066 }
01067 }
01068 return -1;
01069 case RCMD_IDLE:
01070
01071 return 0;
01072 }
01073
01074 req->open = FALSE;
01075
01076 if(req->testno < 0) {
01077 size_t msglen;
01078 char msgbuf[64];
01079
01080 switch(req->testno) {
01081 case DOCNUMBER_QUIT:
01082 logmsg("Replying to QUIT");
01083 buffer = docquit;
01084 break;
01085 case DOCNUMBER_WERULEZ:
01086
01087 logmsg("Identifying ourselves as friends");
01088 snprintf(msgbuf, sizeof(msgbuf), "WE ROOLZ: %ld\r\n", (long)getpid());
01089 msglen = strlen(msgbuf);
01090 if(use_gopher)
01091 snprintf(weare, sizeof(weare), "%s", msgbuf);
01092 else
01093 snprintf(weare, sizeof(weare),
01094 "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
01095 msglen, msgbuf);
01096 buffer = weare;
01097 break;
01098 case DOCNUMBER_404:
01099 default:
01100 logmsg("Replying to with a 404");
01101 buffer = doc404;
01102 break;
01103 }
01104
01105 count = strlen(buffer);
01106 }
01107 else {
01108 char partbuf[80];
01109 char *filename = test2file(req->testno);
01110
01111
01112
01113 const char *section= req->connect_request?"connect":"data";
01114
01115 if(req->partno)
01116 snprintf(partbuf, sizeof(partbuf), "%s%ld", section, req->partno);
01117 else
01118 snprintf(partbuf, sizeof(partbuf), "%s", section);
01119
01120 logmsg("Send response test%ld section <%s>", req->testno, partbuf);
01121
01122 stream=fopen(filename, "rb");
01123 if(!stream) {
01124 error = errno;
01125 logmsg("fopen() failed with error: %d %s", error, strerror(error));
01126 logmsg(" [3] Error opening file: %s", filename);
01127 return 0;
01128 }
01129 else {
01130 error = getpart(&ptr, &count, "reply", partbuf, stream);
01131 fclose(stream);
01132 if(error) {
01133 logmsg("getpart() failed with error: %d", error);
01134 return 0;
01135 }
01136 buffer = ptr;
01137 }
01138
01139 if(got_exit_signal) {
01140 free(ptr);
01141 return -1;
01142 }
01143
01144
01145 stream=fopen(filename, "rb");
01146 if(!stream) {
01147 error = errno;
01148 logmsg("fopen() failed with error: %d %s", error, strerror(error));
01149 logmsg(" [4] Error opening file: %s", filename);
01150 free(ptr);
01151 return 0;
01152 }
01153 else {
01154
01155 error = getpart(&cmd, &cmdsize, "reply", "postcmd", stream);
01156 fclose(stream);
01157 if(error) {
01158 logmsg("getpart() failed with error: %d", error);
01159 free(ptr);
01160 return 0;
01161 }
01162 }
01163 }
01164
01165 if(got_exit_signal) {
01166 free(ptr);
01167 free(cmd);
01168 return -1;
01169 }
01170
01171
01172
01173
01174 if(strstr(buffer, "swsclose") || !count) {
01175 persistant = FALSE;
01176 logmsg("connection close instruction \"swsclose\" found in response");
01177 }
01178 if(strstr(buffer, "swsbounce")) {
01179 prevbounce = TRUE;
01180 logmsg("enable \"swsbounce\" in the next request");
01181 }
01182 else
01183 prevbounce = FALSE;
01184
01185 dump = fopen(responsedump, "ab");
01186 if(!dump) {
01187 error = errno;
01188 logmsg("fopen() failed with error: %d %s", error, strerror(error));
01189 logmsg(" [5] Error opening file: %s", responsedump);
01190 free(ptr);
01191 free(cmd);
01192 return -1;
01193 }
01194
01195 responsesize = count;
01196 do {
01197
01198
01199
01200 size_t num = count;
01201 if(num > 200)
01202 num = 200;
01203 written = swrite(sock, buffer, num);
01204 if(written < 0) {
01205 sendfailure = TRUE;
01206 break;
01207 }
01208 else {
01209 logmsg("Sent off %zd bytes", written);
01210 }
01211
01212 fwrite(buffer, 1, (size_t)written, dump);
01213
01214 count -= written;
01215 buffer += written;
01216
01217 if(req->writedelay) {
01218 int quarters = req->writedelay * 4;
01219 logmsg("Pausing %d seconds", req->writedelay);
01220 while((quarters > 0) && !got_exit_signal) {
01221 quarters--;
01222 wait_ms(250);
01223 }
01224 }
01225 } while((count > 0) && !got_exit_signal);
01226
01227 do {
01228 res = fclose(dump);
01229 } while(res && ((error = errno) == EINTR));
01230 if(res)
01231 logmsg("Error closing file %s error: %d %s",
01232 responsedump, error, strerror(error));
01233
01234 if(got_exit_signal) {
01235 free(ptr);
01236 free(cmd);
01237 return -1;
01238 }
01239
01240 if(sendfailure) {
01241 logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) "
01242 "were sent",
01243 responsesize-count, responsesize);
01244 free(ptr);
01245 free(cmd);
01246 return -1;
01247 }
01248
01249 logmsg("Response sent (%zu bytes) and written to %s",
01250 responsesize, responsedump);
01251 free(ptr);
01252
01253 if(cmdsize > 0) {
01254 char command[32];
01255 int quarters;
01256 int num;
01257 ptr=cmd;
01258 do {
01259 if(2 == sscanf(ptr, "%31s %d", command, &num)) {
01260 if(!strcmp("wait", command)) {
01261 logmsg("Told to sleep for %d seconds", num);
01262 quarters = num * 4;
01263 while((quarters > 0) && !got_exit_signal) {
01264 quarters--;
01265 res = wait_ms(250);
01266 if(res) {
01267
01268 error = errno;
01269 logmsg("wait_ms() failed with error: (%d) %s",
01270 error, strerror(error));
01271 break;
01272 }
01273 }
01274 if(!quarters)
01275 logmsg("Continuing after sleeping %d seconds", num);
01276 }
01277 else
01278 logmsg("Unknown command in reply command section");
01279 }
01280 ptr = strchr(ptr, '\n');
01281 if(ptr)
01282 ptr++;
01283 else
01284 ptr = NULL;
01285 } while(ptr && *ptr);
01286 }
01287 free(cmd);
01288 req->open = use_gopher?FALSE:persistant;
01289
01290 prevtestno = req->testno;
01291 prevpartno = req->partno;
01292
01293 return 0;
01294 }
01295
01296 static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
01297 {
01298 srvr_sockaddr_union_t serveraddr;
01299 curl_socket_t serverfd;
01300 int error;
01301 int rc = 0;
01302 const char *op_br = "";
01303 const char *cl_br = "";
01304
01305 #ifdef ENABLE_IPV6
01306 if(socket_domain == AF_INET6) {
01307 op_br = "[";
01308 cl_br = "]";
01309 }
01310 #endif
01311
01312 if(!ipaddr)
01313 return CURL_SOCKET_BAD;
01314
01315 logmsg("about to connect to %s%s%s:%hu",
01316 op_br, ipaddr, cl_br, port);
01317
01318
01319 serverfd = socket(socket_domain, SOCK_STREAM, 0);
01320 if(CURL_SOCKET_BAD == serverfd) {
01321 error = SOCKERRNO;
01322 logmsg("Error creating socket for server conection: (%d) %s",
01323 error, strerror(error));
01324 return CURL_SOCKET_BAD;
01325 }
01326
01327 #ifdef TCP_NODELAY
01328 if(socket_domain_is_ip()) {
01329
01330 curl_socklen_t flag = 1;
01331 if(0 != setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY,
01332 (void *)&flag, sizeof(flag)))
01333 logmsg("====> TCP_NODELAY for server conection failed");
01334 }
01335 #endif
01336
01337 switch(socket_domain) {
01338 case AF_INET:
01339 memset(&serveraddr.sa4, 0, sizeof(serveraddr.sa4));
01340 serveraddr.sa4.sin_family = AF_INET;
01341 serveraddr.sa4.sin_port = htons(port);
01342 if(Curl_inet_pton(AF_INET, ipaddr, &serveraddr.sa4.sin_addr) < 1) {
01343 logmsg("Error inet_pton failed AF_INET conversion of '%s'", ipaddr);
01344 sclose(serverfd);
01345 return CURL_SOCKET_BAD;
01346 }
01347
01348 rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa4));
01349 break;
01350 #ifdef ENABLE_IPV6
01351 case AF_INET6:
01352 memset(&serveraddr.sa6, 0, sizeof(serveraddr.sa6));
01353 serveraddr.sa6.sin6_family = AF_INET6;
01354 serveraddr.sa6.sin6_port = htons(port);
01355 if(Curl_inet_pton(AF_INET6, ipaddr, &serveraddr.sa6.sin6_addr) < 1) {
01356 logmsg("Error inet_pton failed AF_INET6 conversion of '%s'", ipaddr);
01357 sclose(serverfd);
01358 return CURL_SOCKET_BAD;
01359 }
01360
01361 rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa6));
01362 break;
01363 #endif
01364 #ifdef USE_UNIX_SOCKETS
01365 case AF_UNIX:
01366 logmsg("Proxying through Unix socket is not (yet?) supported.");
01367 return CURL_SOCKET_BAD;
01368 #endif
01369 }
01370
01371 if(got_exit_signal) {
01372 sclose(serverfd);
01373 return CURL_SOCKET_BAD;
01374 }
01375
01376 if(rc) {
01377 error = SOCKERRNO;
01378 logmsg("Error connecting to server port %hu: (%d) %s",
01379 port, error, strerror(error));
01380 sclose(serverfd);
01381 return CURL_SOCKET_BAD;
01382 }
01383
01384 logmsg("connected fine to %s%s%s:%hu, now tunnel",
01385 op_br, ipaddr, cl_br, port);
01386
01387 return serverfd;
01388 }
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402 #define data_or_ctrl(x) ((x)?"DATA":"CTRL")
01403
01404 #define CTRL 0
01405 #define DATA 1
01406
01407 static void http_connect(curl_socket_t *infdp,
01408 curl_socket_t rootfd,
01409 const char *ipaddr,
01410 unsigned short ipport)
01411 {
01412 curl_socket_t serverfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD};
01413 curl_socket_t clientfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD};
01414 ssize_t toc[2] = {0, 0};
01415 ssize_t tos[2] = {0, 0};
01416 char readclient[2][256];
01417 char readserver[2][256];
01418 bool poll_client_rd[2] = { TRUE, TRUE };
01419 bool poll_server_rd[2] = { TRUE, TRUE };
01420 bool poll_client_wr[2] = { TRUE, TRUE };
01421 bool poll_server_wr[2] = { TRUE, TRUE };
01422 bool primary = FALSE;
01423 bool secondary = FALSE;
01424 int max_tunnel_idx;
01425 int loop;
01426 int i;
01427 int timeout_count=0;
01428
01429
01430 clientfd[CTRL] = *infdp;
01431
01432
01433
01434
01435 for(loop = 2; (loop > 0) && !got_exit_signal; loop--)
01436 wait_ms(250);
01437 if(got_exit_signal)
01438 goto http_connect_cleanup;
01439
01440 serverfd[CTRL] = connect_to(ipaddr, ipport);
01441 if(serverfd[CTRL] == CURL_SOCKET_BAD)
01442 goto http_connect_cleanup;
01443
01444
01445
01446
01447
01448
01449 max_tunnel_idx = CTRL;
01450 primary = TRUE;
01451
01452 while(!got_exit_signal) {
01453
01454 fd_set input;
01455 fd_set output;
01456 struct timeval timeout = {1, 0};
01457 ssize_t rc;
01458 curl_socket_t maxfd = (curl_socket_t)-1;
01459
01460 FD_ZERO(&input);
01461 FD_ZERO(&output);
01462
01463 if((clientfd[DATA] == CURL_SOCKET_BAD) &&
01464 (serverfd[DATA] == CURL_SOCKET_BAD) &&
01465 poll_client_rd[CTRL] && poll_client_wr[CTRL] &&
01466 poll_server_rd[CTRL] && poll_server_wr[CTRL]) {
01467
01468
01469
01470 FD_SET(rootfd, &input);
01471 maxfd = rootfd;
01472 }
01473
01474
01475 for(i = 0; i <= max_tunnel_idx; i++) {
01476
01477 if(clientfd[i] != CURL_SOCKET_BAD) {
01478 if(poll_client_rd[i]) {
01479
01480 FD_SET(clientfd[i], &input);
01481 if(clientfd[i] > maxfd)
01482 maxfd = clientfd[i];
01483 }
01484 if(poll_client_wr[i] && toc[i]) {
01485
01486
01487 FD_SET(clientfd[i], &output);
01488 if(clientfd[i] > maxfd)
01489 maxfd = clientfd[i];
01490 }
01491 }
01492
01493 if(serverfd[i] != CURL_SOCKET_BAD) {
01494 if(poll_server_rd[i]) {
01495
01496 FD_SET(serverfd[i], &input);
01497 if(serverfd[i] > maxfd)
01498 maxfd = serverfd[i];
01499 }
01500 if(poll_server_wr[i] && tos[i]) {
01501
01502
01503 FD_SET(serverfd[i], &output);
01504 if(serverfd[i] > maxfd)
01505 maxfd = serverfd[i];
01506 }
01507 }
01508 }
01509 if(got_exit_signal)
01510 break;
01511
01512 rc = select((int)maxfd + 1, &input, &output, NULL, &timeout);
01513
01514 if(rc > 0) {
01515
01516 bool tcp_fin_wr;
01517 timeout_count=0;
01518
01519 if(got_exit_signal)
01520 break;
01521
01522 tcp_fin_wr = FALSE;
01523
01524
01525
01526
01527 if((clientfd[DATA] == CURL_SOCKET_BAD) &&
01528 (serverfd[DATA] == CURL_SOCKET_BAD) && FD_ISSET(rootfd, &input)) {
01529
01530 curl_socket_t datafd = accept(rootfd, NULL, NULL);
01531 if(datafd != CURL_SOCKET_BAD) {
01532 struct httprequest req2;
01533 int err = 0;
01534 memset(&req2, 0, sizeof(req2));
01535 logmsg("====> Client connect DATA");
01536 #ifdef TCP_NODELAY
01537 if(socket_domain_is_ip()) {
01538
01539 curl_socklen_t flag = 1;
01540 if(0 != setsockopt(datafd, IPPROTO_TCP, TCP_NODELAY,
01541 (void *)&flag, sizeof(flag)))
01542 logmsg("====> TCP_NODELAY for client DATA conection failed");
01543 }
01544 #endif
01545 req2.pipelining = FALSE;
01546 init_httprequest(&req2);
01547 while(!req2.done_processing) {
01548 err = get_request(datafd, &req2);
01549 if(err < 0) {
01550
01551 break;
01552 }
01553 }
01554
01555
01556 if(err >= 0) {
01557 err = send_doc(datafd, &req2);
01558 if(!err && req2.connect_request) {
01559
01560 for(loop = 2; (loop > 0) && !got_exit_signal; loop--)
01561 wait_ms(250);
01562 if(!got_exit_signal) {
01563
01564 serverfd[DATA] = connect_to(ipaddr, req2.connect_port);
01565 if(serverfd[DATA] != CURL_SOCKET_BAD) {
01566
01567
01568 poll_client_rd[DATA] = TRUE;
01569 poll_client_wr[DATA] = TRUE;
01570 poll_server_rd[DATA] = TRUE;
01571 poll_server_wr[DATA] = TRUE;
01572 max_tunnel_idx = DATA;
01573 secondary = TRUE;
01574 toc[DATA] = 0;
01575 tos[DATA] = 0;
01576 clientfd[DATA] = datafd;
01577 datafd = CURL_SOCKET_BAD;
01578 }
01579 }
01580 }
01581 }
01582 if(datafd != CURL_SOCKET_BAD) {
01583
01584 shutdown(datafd, SHUT_RDWR);
01585 sclose(datafd);
01586 }
01587 }
01588 if(got_exit_signal)
01589 break;
01590 }
01591
01592
01593
01594
01595 for(i = 0; i <= max_tunnel_idx; i++) {
01596 size_t len;
01597 if(clientfd[i] != CURL_SOCKET_BAD) {
01598 len = sizeof(readclient[i]) - tos[i];
01599 if(len && FD_ISSET(clientfd[i], &input)) {
01600
01601 rc = sread(clientfd[i], &readclient[i][tos[i]], len);
01602 if(rc <= 0) {
01603 logmsg("[%s] got %zd, STOP READING client", data_or_ctrl(i), rc);
01604 shutdown(clientfd[i], SHUT_RD);
01605 poll_client_rd[i] = FALSE;
01606 }
01607 else {
01608 logmsg("[%s] READ %zd bytes from client", data_or_ctrl(i), rc);
01609 logmsg("[%s] READ \"%s\"", data_or_ctrl(i),
01610 data_to_hex(&readclient[i][tos[i]], rc));
01611 tos[i] += rc;
01612 }
01613 }
01614 }
01615 if(serverfd[i] != CURL_SOCKET_BAD) {
01616 len = sizeof(readserver[i])-toc[i];
01617 if(len && FD_ISSET(serverfd[i], &input)) {
01618
01619 rc = sread(serverfd[i], &readserver[i][toc[i]], len);
01620 if(rc <= 0) {
01621 logmsg("[%s] got %zd, STOP READING server", data_or_ctrl(i), rc);
01622 shutdown(serverfd[i], SHUT_RD);
01623 poll_server_rd[i] = FALSE;
01624 }
01625 else {
01626 logmsg("[%s] READ %zd bytes from server", data_or_ctrl(i), rc);
01627 logmsg("[%s] READ \"%s\"", data_or_ctrl(i),
01628 data_to_hex(&readserver[i][toc[i]], rc));
01629 toc[i] += rc;
01630 }
01631 }
01632 }
01633 if(clientfd[i] != CURL_SOCKET_BAD) {
01634 if(toc[i] && FD_ISSET(clientfd[i], &output)) {
01635
01636 rc = swrite(clientfd[i], readserver[i], toc[i]);
01637 if(rc <= 0) {
01638 logmsg("[%s] got %zd, STOP WRITING client", data_or_ctrl(i), rc);
01639 shutdown(clientfd[i], SHUT_WR);
01640 poll_client_wr[i] = FALSE;
01641 tcp_fin_wr = TRUE;
01642 }
01643 else {
01644 logmsg("[%s] SENT %zd bytes to client", data_or_ctrl(i), rc);
01645 logmsg("[%s] SENT \"%s\"", data_or_ctrl(i),
01646 data_to_hex(readserver[i], rc));
01647 if(toc[i] - rc)
01648 memmove(&readserver[i][0], &readserver[i][rc], toc[i]-rc);
01649 toc[i] -= rc;
01650 }
01651 }
01652 }
01653 if(serverfd[i] != CURL_SOCKET_BAD) {
01654 if(tos[i] && FD_ISSET(serverfd[i], &output)) {
01655
01656 rc = swrite(serverfd[i], readclient[i], tos[i]);
01657 if(rc <= 0) {
01658 logmsg("[%s] got %zd, STOP WRITING server", data_or_ctrl(i), rc);
01659 shutdown(serverfd[i], SHUT_WR);
01660 poll_server_wr[i] = FALSE;
01661 tcp_fin_wr = TRUE;
01662 }
01663 else {
01664 logmsg("[%s] SENT %zd bytes to server", data_or_ctrl(i), rc);
01665 logmsg("[%s] SENT \"%s\"", data_or_ctrl(i),
01666 data_to_hex(readclient[i], rc));
01667 if(tos[i] - rc)
01668 memmove(&readclient[i][0], &readclient[i][rc], tos[i]-rc);
01669 tos[i] -= rc;
01670 }
01671 }
01672 }
01673 }
01674 if(got_exit_signal)
01675 break;
01676
01677
01678
01679
01680 for(i = 0; i <= max_tunnel_idx; i++) {
01681 for(loop = 2; loop > 0; loop--) {
01682
01683
01684 if(clientfd[i] != CURL_SOCKET_BAD) {
01685 if(poll_client_rd[i] && !poll_server_wr[i]) {
01686 logmsg("[%s] DISABLED READING client", data_or_ctrl(i));
01687 shutdown(clientfd[i], SHUT_RD);
01688 poll_client_rd[i] = FALSE;
01689 }
01690 if(poll_client_wr[i] && !poll_server_rd[i] && !toc[i]) {
01691 logmsg("[%s] DISABLED WRITING client", data_or_ctrl(i));
01692 shutdown(clientfd[i], SHUT_WR);
01693 poll_client_wr[i] = FALSE;
01694 tcp_fin_wr = TRUE;
01695 }
01696 }
01697 if(serverfd[i] != CURL_SOCKET_BAD) {
01698 if(poll_server_rd[i] && !poll_client_wr[i]) {
01699 logmsg("[%s] DISABLED READING server", data_or_ctrl(i));
01700 shutdown(serverfd[i], SHUT_RD);
01701 poll_server_rd[i] = FALSE;
01702 }
01703 if(poll_server_wr[i] && !poll_client_rd[i] && !tos[i]) {
01704 logmsg("[%s] DISABLED WRITING server", data_or_ctrl(i));
01705 shutdown(serverfd[i], SHUT_WR);
01706 poll_server_wr[i] = FALSE;
01707 tcp_fin_wr = TRUE;
01708 }
01709 }
01710 }
01711 }
01712
01713 if(tcp_fin_wr)
01714
01715 wait_ms(250);
01716
01717
01718 for(i = 0; i <= max_tunnel_idx; i++) {
01719 for(loop = 2; loop > 0; loop--) {
01720 if(clientfd[i] != CURL_SOCKET_BAD) {
01721 if(!poll_client_wr[i] && !poll_client_rd[i]) {
01722 logmsg("[%s] CLOSING client socket", data_or_ctrl(i));
01723 sclose(clientfd[i]);
01724 clientfd[i] = CURL_SOCKET_BAD;
01725 if(serverfd[i] == CURL_SOCKET_BAD) {
01726 logmsg("[%s] ENDING", data_or_ctrl(i));
01727 if(i == DATA)
01728 secondary = FALSE;
01729 else
01730 primary = FALSE;
01731 }
01732 }
01733 }
01734 if(serverfd[i] != CURL_SOCKET_BAD) {
01735 if(!poll_server_wr[i] && !poll_server_rd[i]) {
01736 logmsg("[%s] CLOSING server socket", data_or_ctrl(i));
01737 sclose(serverfd[i]);
01738 serverfd[i] = CURL_SOCKET_BAD;
01739 if(clientfd[i] == CURL_SOCKET_BAD) {
01740 logmsg("[%s] ENDING", data_or_ctrl(i));
01741 if(i == DATA)
01742 secondary = FALSE;
01743 else
01744 primary = FALSE;
01745 }
01746 }
01747 }
01748 }
01749 }
01750
01751
01752
01753 max_tunnel_idx = secondary ? DATA : CTRL;
01754
01755 if(!primary)
01756
01757 break;
01758
01759 }
01760 else {
01761 timeout_count++;
01762 if(timeout_count > 5) {
01763 logmsg("CONNECT proxy timeout after %d idle seconds!", timeout_count);
01764 break;
01765 }
01766 }
01767 }
01768
01769 http_connect_cleanup:
01770
01771 for(i = DATA; i >= CTRL; i--) {
01772 if(serverfd[i] != CURL_SOCKET_BAD) {
01773 logmsg("[%s] CLOSING server socket (cleanup)", data_or_ctrl(i));
01774 shutdown(serverfd[i], SHUT_RDWR);
01775 sclose(serverfd[i]);
01776 }
01777 if(clientfd[i] != CURL_SOCKET_BAD) {
01778 logmsg("[%s] CLOSING client socket (cleanup)", data_or_ctrl(i));
01779 shutdown(clientfd[i], SHUT_RDWR);
01780 sclose(clientfd[i]);
01781 }
01782 if((serverfd[i] != CURL_SOCKET_BAD) ||
01783 (clientfd[i] != CURL_SOCKET_BAD)) {
01784 logmsg("[%s] ABORTING", data_or_ctrl(i));
01785 }
01786 }
01787
01788 *infdp = CURL_SOCKET_BAD;
01789 }
01790
01791 static void http2(struct httprequest *req)
01792 {
01793 (void)req;
01794 logmsg("switched to http2");
01795
01796 }
01797
01798
01799
01800
01801 static curl_socket_t accept_connection(curl_socket_t sock)
01802 {
01803 curl_socket_t msgsock = CURL_SOCKET_BAD;
01804 int error;
01805 int flag = 1;
01806
01807 if(MAX_SOCKETS == num_sockets) {
01808 logmsg("Too many open sockets!");
01809 return CURL_SOCKET_BAD;
01810 }
01811
01812 msgsock = accept(sock, NULL, NULL);
01813
01814 if(got_exit_signal) {
01815 if(CURL_SOCKET_BAD != msgsock)
01816 sclose(msgsock);
01817 return CURL_SOCKET_BAD;
01818 }
01819
01820 if(CURL_SOCKET_BAD == msgsock) {
01821 error = SOCKERRNO;
01822 if(EAGAIN == error || EWOULDBLOCK == error) {
01823
01824 return 0;
01825 }
01826 logmsg("MAJOR ERROR: accept() failed with error: (%d) %s",
01827 error, strerror(error));
01828 return CURL_SOCKET_BAD;
01829 }
01830
01831 if(0 != curlx_nonblock(msgsock, TRUE)) {
01832 error = SOCKERRNO;
01833 logmsg("curlx_nonblock failed with error: (%d) %s",
01834 error, strerror(error));
01835 sclose(msgsock);
01836 return CURL_SOCKET_BAD;
01837 }
01838
01839 if(0 != setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE,
01840 (void *)&flag, sizeof(flag))) {
01841 error = SOCKERRNO;
01842 logmsg("setsockopt(SO_KEEPALIVE) failed with error: (%d) %s",
01843 error, strerror(error));
01844 sclose(msgsock);
01845 return CURL_SOCKET_BAD;
01846 }
01847
01848
01849
01850
01851
01852
01853
01854 if(!serverlogslocked)
01855 set_advisor_read_lock(SERVERLOGS_LOCK);
01856 serverlogslocked += 1;
01857
01858 logmsg("====> Client connect");
01859
01860 all_sockets[num_sockets] = msgsock;
01861 num_sockets += 1;
01862
01863 #ifdef TCP_NODELAY
01864 if(socket_domain_is_ip()) {
01865
01866
01867
01868
01869 if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
01870 (void *)&flag, sizeof(flag)))
01871 logmsg("====> TCP_NODELAY failed");
01872 }
01873 #endif
01874
01875 return msgsock;
01876 }
01877
01878
01879
01880 static int service_connection(curl_socket_t msgsock, struct httprequest *req,
01881 curl_socket_t listensock,
01882 const char *connecthost)
01883 {
01884 if(got_exit_signal)
01885 return -1;
01886
01887 while(!req->done_processing) {
01888 int rc = get_request(msgsock, req);
01889 if(rc <= 0) {
01890
01891 return rc;
01892 }
01893 }
01894
01895 if(prevbounce) {
01896
01897 if((req->testno == prevtestno) &&
01898 (req->partno == prevpartno)) {
01899 req->partno++;
01900 logmsg("BOUNCE part number to %ld", req->partno);
01901 }
01902 else {
01903 prevbounce = FALSE;
01904 prevtestno = -1;
01905 prevpartno = -1;
01906 }
01907 }
01908
01909 send_doc(msgsock, req);
01910 if(got_exit_signal)
01911 return -1;
01912
01913 if(req->testno < 0) {
01914 logmsg("special request received, no persistency");
01915 return -1;
01916 }
01917 if(!req->open) {
01918 logmsg("instructed to close connection after server-reply");
01919 return -1;
01920 }
01921
01922 if(req->connect_request) {
01923
01924 if(!is_proxy) {
01925 logmsg("received CONNECT but isn't running as proxy!");
01926 return 1;
01927 }
01928 else {
01929 http_connect(&msgsock, listensock, connecthost, req->connect_port);
01930 return -1;
01931 }
01932 }
01933
01934 if(req->upgrade_request) {
01935
01936 http2(req);
01937 return -1;
01938 }
01939
01940
01941
01942 if(req->open) {
01943 logmsg("=> persistant connection request ended, awaits new request\n");
01944 return 1;
01945 }
01946
01947 return -1;
01948 }
01949
01950 int main(int argc, char *argv[])
01951 {
01952 srvr_sockaddr_union_t me;
01953 curl_socket_t sock = CURL_SOCKET_BAD;
01954 int wrotepidfile = 0;
01955 int flag;
01956 unsigned short port = DEFAULT_PORT;
01957 #ifdef USE_UNIX_SOCKETS
01958 const char *unix_socket = NULL;
01959 bool unlink_socket = false;
01960 #endif
01961 char *pidname= (char *)".http.pid";
01962 struct httprequest req;
01963 int rc = 0;
01964 int error;
01965 int arg=1;
01966 long pid;
01967 const char *connecthost = "127.0.0.1";
01968 const char *socket_type = "IPv4";
01969 char port_str[11];
01970 const char *location_str = port_str;
01971
01972
01973 size_t socket_idx;
01974
01975 memset(&req, 0, sizeof(req));
01976
01977 while(argc>arg) {
01978 if(!strcmp("--version", argv[arg])) {
01979 puts("sws IPv4"
01980 #ifdef ENABLE_IPV6
01981 "/IPv6"
01982 #endif
01983 #ifdef USE_UNIX_SOCKETS
01984 "/unix"
01985 #endif
01986 );
01987 return 0;
01988 }
01989 else if(!strcmp("--pidfile", argv[arg])) {
01990 arg++;
01991 if(argc>arg)
01992 pidname = argv[arg++];
01993 }
01994 else if(!strcmp("--logfile", argv[arg])) {
01995 arg++;
01996 if(argc>arg)
01997 serverlogfile = argv[arg++];
01998 }
01999 else if(!strcmp("--gopher", argv[arg])) {
02000 arg++;
02001 use_gopher = TRUE;
02002 end_of_headers = "\r\n";
02003 }
02004 else if(!strcmp("--ipv4", argv[arg])) {
02005 socket_type = "IPv4";
02006 socket_domain = AF_INET;
02007 location_str = port_str;
02008 arg++;
02009 }
02010 else if(!strcmp("--ipv6", argv[arg])) {
02011 #ifdef ENABLE_IPV6
02012 socket_type = "IPv6";
02013 socket_domain = AF_INET6;
02014 location_str = port_str;
02015 #endif
02016 arg++;
02017 }
02018 else if(!strcmp("--unix-socket", argv[arg])) {
02019 arg++;
02020 if(argc>arg) {
02021 #ifdef USE_UNIX_SOCKETS
02022 unix_socket = argv[arg];
02023 if(strlen(unix_socket) >= sizeof(me.sau.sun_path)) {
02024 fprintf(stderr, "sws: socket path must be shorter than %zu chars\n",
02025 sizeof(me.sau.sun_path));
02026 return 0;
02027 }
02028 socket_type = "unix";
02029 socket_domain = AF_UNIX;
02030 location_str = unix_socket;
02031 #endif
02032 arg++;
02033 }
02034 }
02035 else if(!strcmp("--port", argv[arg])) {
02036 arg++;
02037 if(argc>arg) {
02038 char *endptr;
02039 unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
02040 if((endptr != argv[arg] + strlen(argv[arg])) ||
02041 (ulnum < 1025UL) || (ulnum > 65535UL)) {
02042 fprintf(stderr, "sws: invalid --port argument (%s)\n",
02043 argv[arg]);
02044 return 0;
02045 }
02046 port = curlx_ultous(ulnum);
02047 arg++;
02048 }
02049 }
02050 else if(!strcmp("--srcdir", argv[arg])) {
02051 arg++;
02052 if(argc>arg) {
02053 path = argv[arg];
02054 arg++;
02055 }
02056 }
02057 else if(!strcmp("--connect", argv[arg])) {
02058
02059
02060
02061 arg++;
02062 if(argc>arg) {
02063 connecthost = argv[arg];
02064 arg++;
02065 is_proxy = TRUE;
02066 logmsg("Run as proxy, CONNECT to host %s", connecthost);
02067 }
02068 }
02069 else {
02070 puts("Usage: sws [option]\n"
02071 " --version\n"
02072 " --logfile [file]\n"
02073 " --pidfile [file]\n"
02074 " --ipv4\n"
02075 " --ipv6\n"
02076 " --unix-socket [file]\n"
02077 " --port [port]\n"
02078 " --srcdir [path]\n"
02079 " --connect [ip4-addr]\n"
02080 " --gopher");
02081 return 0;
02082 }
02083 }
02084
02085 snprintf(port_str, sizeof(port_str), "port %hu", port);
02086
02087 #ifdef WIN32
02088 win32_init();
02089 atexit(win32_cleanup);
02090 #endif
02091
02092 install_signal_handlers();
02093
02094 pid = (long)getpid();
02095
02096 sock = socket(socket_domain, SOCK_STREAM, 0);
02097
02098 all_sockets[0] = sock;
02099 num_sockets = 1;
02100
02101 if(CURL_SOCKET_BAD == sock) {
02102 error = SOCKERRNO;
02103 logmsg("Error creating socket: (%d) %s",
02104 error, strerror(error));
02105 goto sws_cleanup;
02106 }
02107
02108 flag = 1;
02109 if(0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
02110 (void *)&flag, sizeof(flag))) {
02111 error = SOCKERRNO;
02112 logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
02113 error, strerror(error));
02114 goto sws_cleanup;
02115 }
02116 if(0 != curlx_nonblock(sock, TRUE)) {
02117 error = SOCKERRNO;
02118 logmsg("curlx_nonblock failed with error: (%d) %s",
02119 error, strerror(error));
02120 goto sws_cleanup;
02121 }
02122
02123 switch(socket_domain) {
02124 case AF_INET:
02125 memset(&me.sa4, 0, sizeof(me.sa4));
02126 me.sa4.sin_family = AF_INET;
02127 me.sa4.sin_addr.s_addr = INADDR_ANY;
02128 me.sa4.sin_port = htons(port);
02129 rc = bind(sock, &me.sa, sizeof(me.sa4));
02130 break;
02131 #ifdef ENABLE_IPV6
02132 case AF_INET6:
02133 memset(&me.sa6, 0, sizeof(me.sa6));
02134 me.sa6.sin6_family = AF_INET6;
02135 me.sa6.sin6_addr = in6addr_any;
02136 me.sa6.sin6_port = htons(port);
02137 rc = bind(sock, &me.sa, sizeof(me.sa6));
02138 break;
02139 #endif
02140 #ifdef USE_UNIX_SOCKETS
02141 case AF_UNIX:
02142 memset(&me.sau, 0, sizeof(me.sau));
02143 me.sau.sun_family = AF_UNIX;
02144 strncpy(me.sau.sun_path, unix_socket, sizeof(me.sau.sun_path));
02145 rc = bind(sock, &me.sa, sizeof(me.sau));
02146 if(0 != rc && errno == EADDRINUSE) {
02147 struct stat statbuf;
02148
02149 int unixfd = socket(AF_UNIX, SOCK_STREAM, 0);
02150 if(CURL_SOCKET_BAD == unixfd) {
02151 error = SOCKERRNO;
02152 logmsg("Error binding socket, failed to create socket at %s: (%d) %s",
02153 unix_socket, error, strerror(error));
02154 goto sws_cleanup;
02155 }
02156
02157 rc = connect(unixfd, &me.sa, sizeof(me.sau));
02158 error = errno;
02159 close(unixfd);
02160 if(ECONNREFUSED != error) {
02161 logmsg("Error binding socket, failed to connect to %s: (%d) %s",
02162 unix_socket, error, strerror(error));
02163 goto sws_cleanup;
02164 }
02165
02166
02167 rc = lstat(unix_socket, &statbuf);
02168 if(0 != rc) {
02169 logmsg("Error binding socket, failed to stat %s: (%d) %s",
02170 unix_socket, errno, strerror(errno));
02171 goto sws_cleanup;
02172 }
02173 if((statbuf.st_mode & S_IFSOCK) != S_IFSOCK) {
02174 logmsg("Error binding socket, failed to stat %s: (%d) %s",
02175 unix_socket, error, strerror(error));
02176 goto sws_cleanup;
02177 }
02178
02179 rc = unlink(unix_socket);
02180 if(0 != rc) {
02181 logmsg("Error binding socket, failed to unlink %s: (%d) %s",
02182 unix_socket, errno, strerror(errno));
02183 goto sws_cleanup;
02184 }
02185
02186 rc = bind(sock, &me.sa, sizeof(me.sau));
02187 }
02188 break;
02189 #endif
02190 }
02191 if(0 != rc) {
02192 error = SOCKERRNO;
02193 logmsg("Error binding socket on %s: (%d) %s",
02194 location_str, error, strerror(error));
02195 goto sws_cleanup;
02196 }
02197
02198 logmsg("Running %s %s version on %s",
02199 use_gopher?"GOPHER":"HTTP", socket_type, location_str);
02200
02201
02202 rc = listen(sock, 5);
02203 if(0 != rc) {
02204 error = SOCKERRNO;
02205 logmsg("listen() failed with error: (%d) %s",
02206 error, strerror(error));
02207 goto sws_cleanup;
02208 }
02209
02210 #ifdef USE_UNIX_SOCKETS
02211
02212 unlink_socket = true;
02213 #endif
02214
02215
02216
02217
02218
02219
02220 wrotepidfile = write_pidfile(pidname);
02221 if(!wrotepidfile)
02222 goto sws_cleanup;
02223
02224
02225
02226
02227
02228 req.pipelining = FALSE;
02229 init_httprequest(&req);
02230
02231 for(;;) {
02232 fd_set input;
02233 fd_set output;
02234 struct timeval timeout = {0, 250000L};
02235 curl_socket_t maxfd = (curl_socket_t)-1;
02236
02237
02238 for(socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) {
02239 if(CURL_SOCKET_BAD == all_sockets[socket_idx]) {
02240 char *dst = (char *) (all_sockets + socket_idx);
02241 char *src = (char *) (all_sockets + socket_idx + 1);
02242 char *end = (char *) (all_sockets + num_sockets);
02243 memmove(dst, src, end - src);
02244 num_sockets -= 1;
02245 }
02246 }
02247
02248 if(got_exit_signal)
02249 goto sws_cleanup;
02250
02251
02252 FD_ZERO(&input);
02253 FD_ZERO(&output);
02254
02255 for(socket_idx = 0; socket_idx < num_sockets; ++socket_idx) {
02256
02257 FD_SET(all_sockets[socket_idx], &input);
02258 if(all_sockets[socket_idx] > maxfd)
02259 maxfd = all_sockets[socket_idx];
02260 }
02261
02262 if(got_exit_signal)
02263 goto sws_cleanup;
02264
02265 rc = select((int)maxfd + 1, &input, &output, NULL, &timeout);
02266 if(rc < 0) {
02267 error = SOCKERRNO;
02268 logmsg("select() failed with error: (%d) %s",
02269 error, strerror(error));
02270 goto sws_cleanup;
02271 }
02272
02273 if(got_exit_signal)
02274 goto sws_cleanup;
02275
02276 if(rc == 0) {
02277
02278 continue;
02279 }
02280
02281
02282 if(FD_ISSET(all_sockets[0], &input)) {
02283
02284 curl_socket_t msgsock;
02285 do {
02286 msgsock = accept_connection(sock);
02287 logmsg("accept_connection %d returned %d", sock, msgsock);
02288 if(CURL_SOCKET_BAD == msgsock)
02289 goto sws_cleanup;
02290 } while(msgsock > 0);
02291 }
02292
02293
02294 for(socket_idx = 1; socket_idx < num_sockets; ++socket_idx) {
02295 if(FD_ISSET(all_sockets[socket_idx], &input)) {
02296 if(got_exit_signal)
02297 goto sws_cleanup;
02298
02299
02300 do {
02301 rc = service_connection(all_sockets[socket_idx], &req, sock,
02302 connecthost);
02303 if(got_exit_signal)
02304 goto sws_cleanup;
02305
02306 if(rc < 0) {
02307 logmsg("====> Client disconnect %d", req.connmon);
02308
02309 if(req.connmon) {
02310 const char *keepopen="[DISCONNECT]\n";
02311 storerequest((char *)keepopen, strlen(keepopen));
02312 }
02313
02314 if(!req.open)
02315
02316
02317
02318
02319 wait_ms(50);
02320
02321 if(all_sockets[socket_idx] != CURL_SOCKET_BAD) {
02322 sclose(all_sockets[socket_idx]);
02323 all_sockets[socket_idx] = CURL_SOCKET_BAD;
02324 }
02325
02326 serverlogslocked -= 1;
02327 if(!serverlogslocked)
02328 clear_advisor_read_lock(SERVERLOGS_LOCK);
02329
02330 if(req.testno == DOCNUMBER_QUIT)
02331 goto sws_cleanup;
02332 }
02333
02334
02335 if(rc != 0)
02336 init_httprequest(&req);
02337 } while(rc > 0);
02338 }
02339 }
02340
02341 if(got_exit_signal)
02342 goto sws_cleanup;
02343 }
02344
02345 sws_cleanup:
02346
02347 for(socket_idx = 1; socket_idx < num_sockets; ++socket_idx)
02348 if((all_sockets[socket_idx] != sock) &&
02349 (all_sockets[socket_idx] != CURL_SOCKET_BAD))
02350 sclose(all_sockets[socket_idx]);
02351
02352 if(sock != CURL_SOCKET_BAD)
02353 sclose(sock);
02354
02355 #ifdef USE_UNIX_SOCKETS
02356 if(unlink_socket && socket_domain == AF_UNIX) {
02357 rc = unlink(unix_socket);
02358 logmsg("unlink(%s) = %d (%s)", unix_socket, rc, strerror(rc));
02359 }
02360 #endif
02361
02362 if(got_exit_signal)
02363 logmsg("signalled to die");
02364
02365 if(wrotepidfile)
02366 unlink(pidname);
02367
02368 if(serverlogslocked) {
02369 serverlogslocked = 0;
02370 clear_advisor_read_lock(SERVERLOGS_LOCK);
02371 }
02372
02373 restore_signal_handlers();
02374
02375 if(got_exit_signal) {
02376 logmsg("========> %s sws (%s pid: %ld) exits with signal (%d)",
02377 socket_type, location_str, pid, exit_signal);
02378
02379
02380
02381
02382
02383 raise(exit_signal);
02384 }
02385
02386 logmsg("========> sws quits");
02387 return 0;
02388 }
02389