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