Revert "Imported Upstream version 7.44.0"
[platform/upstream/curl.git] / tests / server / sws.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@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 http://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     if(orgcmd)
446       free(orgcmd);
447   }
448
449   return 0; /* OK! */
450 }
451
452 static int ProcessRequest(struct httprequest *req)
453 {
454   char *line=&req->reqbuf[req->checkindex];
455   bool chunked = FALSE;
456   static char request[REQUEST_KEYWORD_SIZE];
457   static char doc[MAXDOCNAMELEN];
458   char logbuf[456];
459   int prot_major, prot_minor;
460   char *end = strstr(line, end_of_headers);
461
462   req->callcount++;
463
464   logmsg("Process %d bytes request%s", req->offset,
465          req->callcount > 1?" [CONTINUED]":"");
466
467   /* try to figure out the request characteristics as soon as possible, but
468      only once! */
469
470   if(use_gopher &&
471      (req->testno == DOCNUMBER_NOTHING) &&
472      !strncmp("/verifiedserver", line, 15)) {
473     logmsg("Are-we-friendly question received");
474     req->testno = DOCNUMBER_WERULEZ;
475     return 1; /* done */
476   }
477
478   else if((req->testno == DOCNUMBER_NOTHING) &&
479      sscanf(line,
480             "%" REQUEST_KEYWORD_SIZE_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
481             request,
482             doc,
483             &prot_major,
484             &prot_minor) == 4) {
485     char *ptr;
486
487     req->prot_version = prot_major*10 + prot_minor;
488
489     /* find the last slash */
490     ptr = strrchr(doc, '/');
491
492     /* get the number after it */
493     if(ptr) {
494       if((strlen(doc) + strlen(request)) < 400)
495         sprintf(logbuf, "Got request: %s %s HTTP/%d.%d",
496                 request, doc, prot_major, prot_minor);
497       else
498         sprintf(logbuf, "Got a *HUGE* request HTTP/%d.%d",
499                 prot_major, prot_minor);
500       logmsg("%s", logbuf);
501
502       if(!strncmp("/verifiedserver", ptr, 15)) {
503         logmsg("Are-we-friendly question received");
504         req->testno = DOCNUMBER_WERULEZ;
505         return 1; /* done */
506       }
507
508       if(!strncmp("/quit", ptr, 5)) {
509         logmsg("Request-to-quit received");
510         req->testno = DOCNUMBER_QUIT;
511         return 1; /* done */
512       }
513
514       ptr++; /* skip the slash */
515
516       /* skip all non-numericals following the slash */
517       while(*ptr && !ISDIGIT(*ptr))
518         ptr++;
519
520       req->testno = strtol(ptr, &ptr, 10);
521
522       if(req->testno > 10000) {
523         req->partno = req->testno % 10000;
524         req->testno /= 10000;
525       }
526       else
527         req->partno = 0;
528
529       if(req->testno) {
530
531         sprintf(logbuf, "Requested test number %ld part %ld",
532                 req->testno, req->partno);
533         logmsg("%s", logbuf);
534
535         /* find and parse <servercmd> for this test */
536         parse_servercmd(req);
537       }
538       else
539         req->testno = DOCNUMBER_NOTHING;
540
541     }
542
543     if(req->testno == DOCNUMBER_NOTHING) {
544       /* didn't find any in the first scan, try alternative test case
545          number placements */
546
547       if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
548                 doc, &prot_major, &prot_minor) == 3) {
549         char *portp = NULL;
550         unsigned long part=0;
551
552         sprintf(logbuf, "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         sprintf(logbuf, "Requested test number %ld part %ld (from host name)",
623                 req->testno, req->partno);
624         logmsg("%s", logbuf);
625
626       }
627
628       if(!req->testno) {
629         logmsg("Did not find test number in PATH");
630         req->testno = DOCNUMBER_404;
631       }
632       else
633         parse_servercmd(req);
634     }
635   }
636   else if((req->offset >= 3) && (req->testno == DOCNUMBER_NOTHING)) {
637     logmsg("** Unusual request. Starts with %02x %02x %02x",
638            line[0], line[1], line[2]);
639   }
640
641   if(!end) {
642     /* we don't have a complete request yet! */
643     logmsg("request not complete yet");
644     return 0; /* not complete yet */
645   }
646   logmsg("- request found to be complete");
647
648   if(use_gopher) {
649     /* when using gopher we cannot check the request until the entire
650        thing has been received */
651     char *ptr;
652
653     /* find the last slash in the line */
654     ptr = strrchr(line, '/');
655
656     if(ptr) {
657       ptr++; /* skip the slash */
658
659       /* skip all non-numericals following the slash */
660       while(*ptr && !ISDIGIT(*ptr))
661         ptr++;
662
663       req->testno = strtol(ptr, &ptr, 10);
664
665       if(req->testno > 10000) {
666         req->partno = req->testno % 10000;
667         req->testno /= 10000;
668       }
669       else
670         req->partno = 0;
671
672       sprintf(logbuf, "Requested GOPHER test number %ld part %ld",
673               req->testno, req->partno);
674       logmsg("%s", logbuf);
675     }
676   }
677
678   if(req->pipe)
679     /* we do have a full set, advance the checkindex to after the end of the
680        headers, for the pipelining case mostly */
681     req->checkindex += (end - line) + strlen(end_of_headers);
682
683   /* **** Persistence ****
684    *
685    * If the request is a HTTP/1.0 one, we close the connection unconditionally
686    * when we're done.
687    *
688    * If the request is a HTTP/1.1 one, we MUST check for a "Connection:"
689    * header that might say "close". If it does, we close a connection when
690    * this request is processed. Otherwise, we keep the connection alive for X
691    * seconds.
692    */
693
694   do {
695     if(got_exit_signal)
696       return 1; /* done */
697
698     if((req->cl==0) && curlx_strnequal("Content-Length:", line, 15)) {
699       /* If we don't ignore content-length, we read it and we read the whole
700          request including the body before we return. If we've been told to
701          ignore the content-length, we will return as soon as all headers
702          have been received */
703       char *endptr;
704       char *ptr = line + 15;
705       unsigned long clen = 0;
706       while(*ptr && ISSPACE(*ptr))
707         ptr++;
708       endptr = ptr;
709       errno = 0;
710       clen = strtoul(ptr, &endptr, 10);
711       if((ptr == endptr) || !ISSPACE(*endptr) || (ERANGE == errno)) {
712         /* this assumes that a zero Content-Length is valid */
713         logmsg("Found invalid Content-Length: (%s) in the request", ptr);
714         req->open = FALSE; /* closes connection */
715         return 1; /* done */
716       }
717       req->cl = clen - req->skip;
718
719       logmsg("Found Content-Length: %lu in the request", clen);
720       if(req->skip)
721         logmsg("... but will abort after %zu bytes", req->cl);
722       break;
723     }
724     else if(curlx_strnequal("Transfer-Encoding: chunked", line,
725                             strlen("Transfer-Encoding: chunked"))) {
726       /* chunked data coming in */
727       chunked = TRUE;
728     }
729
730     if(chunked) {
731       if(strstr(req->reqbuf, "\r\n0\r\n\r\n"))
732         /* end of chunks reached */
733         return 1; /* done */
734       else
735         return 0; /* not done */
736     }
737
738     line = strchr(line, '\n');
739     if(line)
740       line++;
741
742   } while(line);
743
744   if(!req->auth && strstr(req->reqbuf, "Authorization:")) {
745     req->auth = TRUE; /* Authorization: header present! */
746     if(req->auth_req)
747       logmsg("Authorization header found, as required");
748   }
749
750   if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
751     /* If the client is passing this Digest-header, we set the part number
752        to 1000. Not only to spice up the complexity of this, but to make
753        Digest stuff to work in the test suite. */
754     req->partno += 1000;
755     req->digest = TRUE; /* header found */
756     logmsg("Received Digest request, sending back data %ld", req->partno);
757   }
758   else if(!req->ntlm &&
759           strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) {
760     /* If the client is passing this type-3 NTLM header */
761     req->partno += 1002;
762     req->ntlm = TRUE; /* NTLM found */
763     logmsg("Received NTLM type-3, sending back data %ld", req->partno);
764     if(req->cl) {
765       logmsg("  Expecting %zu POSTed bytes", req->cl);
766     }
767   }
768   else if(!req->ntlm &&
769           strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) {
770     /* If the client is passing this type-1 NTLM header */
771     req->partno += 1001;
772     req->ntlm = TRUE; /* NTLM found */
773     logmsg("Received NTLM type-1, sending back data %ld", req->partno);
774   }
775   else if((req->partno >= 1000) &&
776           strstr(req->reqbuf, "Authorization: Basic")) {
777     /* If the client is passing this Basic-header and the part number is
778        already >=1000, we add 1 to the part number.  This allows simple Basic
779        authentication negotiation to work in the test suite. */
780     req->partno += 1;
781     logmsg("Received Basic request, sending back data %ld", req->partno);
782   }
783   if(strstr(req->reqbuf, "Connection: close"))
784     req->open = FALSE; /* close connection after this request */
785
786   if(!req->pipe &&
787      req->open &&
788      req->prot_version >= 11 &&
789      end &&
790      req->reqbuf + req->offset > end + strlen(end_of_headers) &&
791      !req->cl &&
792      (!strncmp(req->reqbuf, "GET", strlen("GET")) ||
793       !strncmp(req->reqbuf, "HEAD", strlen("HEAD")))) {
794     /* If we have a persistent connection, HTTP version >= 1.1
795        and GET/HEAD request, enable pipelining. */
796     req->checkindex = (end - req->reqbuf) + strlen(end_of_headers);
797     req->pipelining = TRUE;
798   }
799
800   while(req->pipe) {
801     if(got_exit_signal)
802       return 1; /* done */
803     /* scan for more header ends within this chunk */
804     line = &req->reqbuf[req->checkindex];
805     end = strstr(line, end_of_headers);
806     if(!end)
807       break;
808     req->checkindex += (end - line) + strlen(end_of_headers);
809     req->pipe--;
810   }
811
812   /* If authentication is required and no auth was provided, end now. This
813      makes the server NOT wait for PUT/POST data and you can then make the
814      test case send a rejection before any such data has been sent. Test case
815      154 uses this.*/
816   if(req->auth_req && !req->auth) {
817     logmsg("Return early due to auth requested by none provided");
818     return 1; /* done */
819   }
820
821   if(req->upgrade && strstr(req->reqbuf, "Upgrade:")) {
822     /* we allow upgrade and there was one! */
823     logmsg("Found Upgrade: in request and allows it");
824     req->upgrade_request = TRUE;
825   }
826
827   if(req->cl > 0) {
828     if(req->cl <= req->offset - (end - req->reqbuf) - strlen(end_of_headers))
829       return 1; /* done */
830     else
831       return 0; /* not complete yet */
832   }
833
834   return 1; /* done */
835 }
836
837 /* store the entire request in a file */
838 static void storerequest(char *reqbuf, size_t totalsize)
839 {
840   int res;
841   int error = 0;
842   size_t written;
843   size_t writeleft;
844   FILE *dump;
845   const char *dumpfile=is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP;
846
847   if (reqbuf == NULL)
848     return;
849   if (totalsize == 0)
850     return;
851
852   do {
853     dump = fopen(dumpfile, "ab");
854   } while ((dump == NULL) && ((error = errno) == EINTR));
855   if (dump == NULL) {
856     logmsg("[2] Error opening file %s error: %d %s",
857            dumpfile, error, strerror(error));
858     logmsg("Failed to write request input ");
859     return;
860   }
861
862   writeleft = totalsize;
863   do {
864     written = fwrite(&reqbuf[totalsize-writeleft],
865                      1, writeleft, dump);
866     if(got_exit_signal)
867       goto storerequest_cleanup;
868     if(written > 0)
869       writeleft -= written;
870   } while ((writeleft > 0) && ((error = errno) == EINTR));
871
872   if(writeleft == 0)
873     logmsg("Wrote request (%zu bytes) input to %s", totalsize, dumpfile);
874   else if(writeleft > 0) {
875     logmsg("Error writing file %s error: %d %s",
876            dumpfile, error, strerror(error));
877     logmsg("Wrote only (%zu bytes) of (%zu bytes) request input to %s",
878            totalsize-writeleft, totalsize, dumpfile);
879   }
880
881 storerequest_cleanup:
882
883   do {
884     res = fclose(dump);
885   } while(res && ((error = errno) == EINTR));
886   if(res)
887     logmsg("Error closing file %s error: %d %s",
888            dumpfile, error, strerror(error));
889 }
890
891 static void init_httprequest(struct httprequest *req)
892 {
893   /* Pipelining is already set, so do not initialize it here. Only initialize
894      checkindex and offset if pipelining is not set, since in a pipeline they
895      need to be inherited from the previous request. */
896   if(!req->pipelining) {
897     req->checkindex = 0;
898     req->offset = 0;
899   }
900   req->testno = DOCNUMBER_NOTHING;
901   req->partno = 0;
902   req->connect_request = FALSE;
903   req->open = TRUE;
904   req->auth_req = FALSE;
905   req->auth = FALSE;
906   req->cl = 0;
907   req->digest = FALSE;
908   req->ntlm = FALSE;
909   req->pipe = 0;
910   req->skip = 0;
911   req->writedelay = 0;
912   req->rcmd = RCMD_NORMALREQ;
913   req->prot_version = 0;
914   req->callcount = 0;
915   req->connect_port = 0;
916   req->done_processing = 0;
917 }
918
919 /* returns 1 if the connection should be serviced again immediately, 0 if there
920    is no data waiting, or < 0 if it should be closed */
921 static int get_request(curl_socket_t sock, struct httprequest *req)
922 {
923   int error;
924   int fail = 0;
925   char *reqbuf = req->reqbuf;
926   ssize_t got = 0;
927   int overflow = 0;
928
929   char *pipereq = NULL;
930   size_t pipereq_length = 0;
931
932   if(req->pipelining) {
933     pipereq = reqbuf + req->checkindex;
934     pipereq_length = req->offset - req->checkindex;
935
936     /* Now that we've got the pipelining info we can reset the
937        pipelining-related vars which were skipped in init_httprequest */
938     req->pipelining = FALSE;
939     req->checkindex = 0;
940     req->offset = 0;
941   }
942
943   if(req->offset >= REQBUFSIZ-1) {
944     /* buffer is already full; do nothing */
945     overflow = 1;
946   }
947   else {
948     if(pipereq_length && pipereq) {
949       memmove(reqbuf, pipereq, pipereq_length);
950       got = curlx_uztosz(pipereq_length);
951       pipereq_length = 0;
952     }
953     else {
954       if(req->skip)
955         /* we are instructed to not read the entire thing, so we make sure to
956            only read what we're supposed to and NOT read the enire thing the
957            client wants to send! */
958         got = sread(sock, reqbuf + req->offset, req->cl);
959       else
960         got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset);
961     }
962     if(got_exit_signal)
963       return -1;
964     if(got == 0) {
965       logmsg("Connection closed by client");
966       fail = 1;
967     }
968     else if(got < 0) {
969       error = SOCKERRNO;
970       if (EAGAIN == error || EWOULDBLOCK == error) {
971         /* nothing to read at the moment */
972         return 0;
973       }
974       logmsg("recv() returned error: (%d) %s", error, strerror(error));
975       fail = 1;
976     }
977     if(fail) {
978       /* dump the request received so far to the external file */
979       reqbuf[req->offset] = '\0';
980       storerequest(reqbuf, req->offset);
981       return -1;
982     }
983
984     logmsg("Read %zd bytes", got);
985
986     req->offset += (size_t)got;
987     reqbuf[req->offset] = '\0';
988
989     req->done_processing = ProcessRequest(req);
990     if(got_exit_signal)
991       return -1;
992     if(req->done_processing && req->pipe) {
993       logmsg("Waiting for another piped request");
994       req->done_processing = 0;
995       req->pipe--;
996     }
997   }
998
999   if(overflow || (req->offset == REQBUFSIZ-1 && got > 0)) {
1000     logmsg("Request would overflow buffer, closing connection");
1001     /* dump request received so far to external file anyway */
1002     reqbuf[REQBUFSIZ-1] = '\0';
1003     fail = 1;
1004   }
1005   else if(req->offset > REQBUFSIZ-1) {
1006     logmsg("Request buffer overflow, closing connection");
1007     /* dump request received so far to external file anyway */
1008     reqbuf[REQBUFSIZ-1] = '\0';
1009     fail = 1;
1010   }
1011   else
1012     reqbuf[req->offset] = '\0';
1013
1014   /* at the end of a request dump it to an external file */
1015   if (fail || req->done_processing)
1016     storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
1017   if(got_exit_signal)
1018     return -1;
1019
1020   return fail ? -1 : 1;
1021 }
1022
1023 /* returns -1 on failure */
1024 static int send_doc(curl_socket_t sock, struct httprequest *req)
1025 {
1026   ssize_t written;
1027   size_t count;
1028   const char *buffer;
1029   char *ptr=NULL;
1030   FILE *stream;
1031   char *cmd=NULL;
1032   size_t cmdsize=0;
1033   FILE *dump;
1034   bool persistant = TRUE;
1035   bool sendfailure = FALSE;
1036   size_t responsesize;
1037   int error = 0;
1038   int res;
1039   const char *responsedump = is_proxy?RESPONSE_PROXY_DUMP:RESPONSE_DUMP;
1040   static char weare[256];
1041
1042   switch(req->rcmd) {
1043   default:
1044   case RCMD_NORMALREQ:
1045     break; /* continue with business as usual */
1046   case RCMD_STREAM:
1047 #define STREAMTHIS "a string to stream 01234567890\n"
1048     count = strlen(STREAMTHIS);
1049     for (;;) {
1050       written = swrite(sock, STREAMTHIS, count);
1051       if(got_exit_signal)
1052         return -1;
1053       if(written != (ssize_t)count) {
1054         logmsg("Stopped streaming");
1055         break;
1056       }
1057     }
1058     return -1;
1059   case RCMD_IDLE:
1060     /* Do nothing. Sit idle. Pretend it rains. */
1061     return 0;
1062   }
1063
1064   req->open = FALSE;
1065
1066   if(req->testno < 0) {
1067     size_t msglen;
1068     char msgbuf[64];
1069
1070     switch(req->testno) {
1071     case DOCNUMBER_QUIT:
1072       logmsg("Replying to QUIT");
1073       buffer = docquit;
1074       break;
1075     case DOCNUMBER_WERULEZ:
1076       /* we got a "friends?" question, reply back that we sure are */
1077       logmsg("Identifying ourselves as friends");
1078       sprintf(msgbuf, "WE ROOLZ: %ld\r\n", (long)getpid());
1079       msglen = strlen(msgbuf);
1080       if(use_gopher)
1081         sprintf(weare, "%s", msgbuf);
1082       else
1083         sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
1084                 msglen, msgbuf);
1085       buffer = weare;
1086       break;
1087     case DOCNUMBER_404:
1088     default:
1089       logmsg("Replying to with a 404");
1090       buffer = doc404;
1091       break;
1092     }
1093
1094     count = strlen(buffer);
1095   }
1096   else {
1097     char partbuf[80];
1098     char *filename = test2file(req->testno);
1099
1100     /* select the <data> tag for "normal" requests and the <connect> one
1101        for CONNECT requests (within the <reply> section) */
1102     const char *section= req->connect_request?"connect":"data";
1103
1104     if(req->partno)
1105       sprintf(partbuf, "%s%ld", section, req->partno);
1106     else
1107       sprintf(partbuf, "%s", section);
1108
1109     logmsg("Send response test%ld section <%s>", req->testno, partbuf);
1110
1111     stream=fopen(filename, "rb");
1112     if(!stream) {
1113       error = errno;
1114       logmsg("fopen() failed with error: %d %s", error, strerror(error));
1115       logmsg("  [3] Error opening file: %s", filename);
1116       return 0;
1117     }
1118     else {
1119       error = getpart(&ptr, &count, "reply", partbuf, stream);
1120       fclose(stream);
1121       if(error) {
1122         logmsg("getpart() failed with error: %d", error);
1123         return 0;
1124       }
1125       buffer = ptr;
1126     }
1127
1128     if(got_exit_signal) {
1129       if(ptr)
1130         free(ptr);
1131       return -1;
1132     }
1133
1134     /* re-open the same file again */
1135     stream=fopen(filename, "rb");
1136     if(!stream) {
1137       error = errno;
1138       logmsg("fopen() failed with error: %d %s", error, strerror(error));
1139       logmsg("  [4] Error opening file: %s", filename);
1140       if(ptr)
1141         free(ptr);
1142       return 0;
1143     }
1144     else {
1145       /* get the custom server control "commands" */
1146       error = getpart(&cmd, &cmdsize, "reply", "postcmd", stream);
1147       fclose(stream);
1148       if(error) {
1149         logmsg("getpart() failed with error: %d", error);
1150         if(ptr)
1151           free(ptr);
1152         return 0;
1153       }
1154     }
1155   }
1156
1157   if(got_exit_signal) {
1158     if(ptr)
1159       free(ptr);
1160     if(cmd)
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     if(ptr)
1185       free(ptr);
1186     if(cmd)
1187       free(cmd);
1188     return -1;
1189   }
1190
1191   responsesize = count;
1192   do {
1193     /* Ok, we send no more than 200 bytes at a time, just to make sure that
1194        larger chunks are split up so that the client will need to do multiple
1195        recv() calls to get it and thus we exercise that code better */
1196     size_t num = count;
1197     if(num > 200)
1198       num = 200;
1199     written = swrite(sock, buffer, num);
1200     if (written < 0) {
1201       sendfailure = TRUE;
1202       break;
1203     }
1204     else {
1205       logmsg("Sent off %zd bytes", written);
1206     }
1207     /* write to file as well */
1208     fwrite(buffer, 1, (size_t)written, dump);
1209
1210     count -= written;
1211     buffer += written;
1212
1213     if(req->writedelay) {
1214       int quarters = req->writedelay * 4;
1215       logmsg("Pausing %d seconds", req->writedelay);
1216       while((quarters > 0) && !got_exit_signal) {
1217         quarters--;
1218         wait_ms(250);
1219       }
1220     }
1221   } while((count > 0) && !got_exit_signal);
1222
1223   do {
1224     res = fclose(dump);
1225   } while(res && ((error = errno) == EINTR));
1226   if(res)
1227     logmsg("Error closing file %s error: %d %s",
1228            responsedump, error, strerror(error));
1229
1230   if(got_exit_signal) {
1231     if(ptr)
1232       free(ptr);
1233     if(cmd)
1234       free(cmd);
1235     return -1;
1236   }
1237
1238   if(sendfailure) {
1239     logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) were sent",
1240            responsesize-count, responsesize);
1241     if(ptr)
1242       free(ptr);
1243     if(cmd)
1244       free(cmd);
1245     return -1;
1246   }
1247
1248   logmsg("Response sent (%zu bytes) and written to %s",
1249          responsesize, responsedump);
1250
1251   if(ptr)
1252     free(ptr);
1253
1254   if(cmdsize > 0 ) {
1255     char command[32];
1256     int quarters;
1257     int num;
1258     ptr=cmd;
1259     do {
1260       if(2 == sscanf(ptr, "%31s %d", command, &num)) {
1261         if(!strcmp("wait", command)) {
1262           logmsg("Told to sleep for %d seconds", num);
1263           quarters = num * 4;
1264           while((quarters > 0) && !got_exit_signal) {
1265             quarters--;
1266             res = wait_ms(250);
1267             if(res) {
1268               /* should not happen */
1269               error = errno;
1270               logmsg("wait_ms() failed with error: (%d) %s",
1271                      error, strerror(error));
1272               break;
1273             }
1274           }
1275           if(!quarters)
1276             logmsg("Continuing after sleeping %d seconds", num);
1277         }
1278         else
1279           logmsg("Unknown command in reply command section");
1280       }
1281       ptr = strchr(ptr, '\n');
1282       if(ptr)
1283         ptr++;
1284       else
1285         ptr = NULL;
1286     } while(ptr && *ptr);
1287   }
1288   if(cmd)
1289     free(cmd);
1290
1291   req->open = use_gopher?FALSE:persistant;
1292
1293   prevtestno = req->testno;
1294   prevpartno = req->partno;
1295
1296   return 0;
1297 }
1298
1299 static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
1300 {
1301   srvr_sockaddr_union_t serveraddr;
1302   curl_socket_t serverfd;
1303   int error;
1304   int rc = 0;
1305   const char *op_br = "";
1306   const char *cl_br = "";
1307
1308 #ifdef ENABLE_IPV6
1309   if(socket_domain == AF_INET6) {
1310     op_br = "[";
1311     cl_br = "]";
1312   }
1313 #endif
1314
1315   if(!ipaddr)
1316     return CURL_SOCKET_BAD;
1317
1318   logmsg("about to connect to %s%s%s:%hu",
1319          op_br, ipaddr, cl_br, port);
1320
1321
1322   serverfd = socket(socket_domain, SOCK_STREAM, 0);
1323   if(CURL_SOCKET_BAD == serverfd) {
1324     error = SOCKERRNO;
1325     logmsg("Error creating socket for server conection: (%d) %s",
1326            error, strerror(error));
1327     return CURL_SOCKET_BAD;
1328   }
1329
1330 #ifdef TCP_NODELAY
1331   if(socket_domain_is_ip()) {
1332     /* Disable the Nagle algorithm */
1333     curl_socklen_t flag = 1;
1334     if(0 != setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY,
1335                        (void *)&flag, sizeof(flag)))
1336       logmsg("====> TCP_NODELAY for server conection failed");
1337     else
1338       logmsg("TCP_NODELAY set for server conection");
1339   }
1340 #endif
1341
1342   switch(socket_domain) {
1343   case AF_INET:
1344     memset(&serveraddr.sa4, 0, sizeof(serveraddr.sa4));
1345     serveraddr.sa4.sin_family = AF_INET;
1346     serveraddr.sa4.sin_port = htons(port);
1347     if(Curl_inet_pton(AF_INET, ipaddr, &serveraddr.sa4.sin_addr) < 1) {
1348       logmsg("Error inet_pton failed AF_INET conversion of '%s'", ipaddr);
1349       sclose(serverfd);
1350       return CURL_SOCKET_BAD;
1351     }
1352
1353     rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa4));
1354     break;
1355 #ifdef ENABLE_IPV6
1356   case AF_INET6:
1357     memset(&serveraddr.sa6, 0, sizeof(serveraddr.sa6));
1358     serveraddr.sa6.sin6_family = AF_INET6;
1359     serveraddr.sa6.sin6_port = htons(port);
1360     if(Curl_inet_pton(AF_INET6, ipaddr, &serveraddr.sa6.sin6_addr) < 1) {
1361       logmsg("Error inet_pton failed AF_INET6 conversion of '%s'", ipaddr);
1362       sclose(serverfd);
1363       return CURL_SOCKET_BAD;
1364     }
1365
1366     rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa6));
1367     break;
1368 #endif /* ENABLE_IPV6 */
1369 #ifdef USE_UNIX_SOCKETS
1370   case AF_UNIX:
1371     logmsg("Proxying through Unix socket is not (yet?) supported.");
1372     return CURL_SOCKET_BAD;
1373 #endif /* USE_UNIX_SOCKETS */
1374   }
1375
1376   if(got_exit_signal) {
1377     sclose(serverfd);
1378     return CURL_SOCKET_BAD;
1379   }
1380
1381   if(rc) {
1382     error = SOCKERRNO;
1383     logmsg("Error connecting to server port %hu: (%d) %s",
1384            port, error, strerror(error));
1385     sclose(serverfd);
1386     return CURL_SOCKET_BAD;
1387   }
1388
1389   logmsg("connected fine to %s%s%s:%hu, now tunnel",
1390          op_br, ipaddr, cl_br, port);
1391
1392   return serverfd;
1393 }
1394
1395 /*
1396  * A CONNECT has been received, a CONNECT response has been sent.
1397  *
1398  * This function needs to connect to the server, and then pass data between
1399  * the client and the server back and forth until the connection is closed by
1400  * either end.
1401  *
1402  * When doing FTP through a CONNECT proxy, we expect that the data connection
1403  * will be setup while the first connect is still being kept up. Therefor we
1404  * must accept a new connection and deal with it appropriately.
1405  */
1406
1407 #define data_or_ctrl(x) ((x)?"DATA":"CTRL")
1408
1409 #define CTRL  0
1410 #define DATA  1
1411
1412 static void http_connect(curl_socket_t *infdp,
1413                          curl_socket_t rootfd,
1414                          const char *ipaddr,
1415                          unsigned short ipport)
1416 {
1417   curl_socket_t serverfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD};
1418   curl_socket_t clientfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD};
1419   ssize_t toc[2] = {0, 0}; /* number of bytes to client */
1420   ssize_t tos[2] = {0, 0}; /* number of bytes to server */
1421   char readclient[2][256];
1422   char readserver[2][256];
1423   bool poll_client_rd[2] = { TRUE, TRUE };
1424   bool poll_server_rd[2] = { TRUE, TRUE };
1425   bool poll_client_wr[2] = { TRUE, TRUE };
1426   bool poll_server_wr[2] = { TRUE, TRUE };
1427   bool primary = FALSE;
1428   bool secondary = FALSE;
1429   int max_tunnel_idx; /* CTRL or DATA */
1430   int loop;
1431   int i;
1432
1433   /* primary tunnel client endpoint already connected */
1434   clientfd[CTRL] = *infdp;
1435
1436   /* Sleep here to make sure the client reads CONNECT response's
1437      'end of headers' separate from the server data that follows.
1438      This is done to prevent triggering libcurl known bug #39. */
1439   for(loop = 2; (loop > 0) && !got_exit_signal; loop--)
1440     wait_ms(250);
1441   if(got_exit_signal)
1442     goto http_connect_cleanup;
1443
1444   serverfd[CTRL] = connect_to(ipaddr, ipport);
1445   if(serverfd[CTRL] == CURL_SOCKET_BAD)
1446     goto http_connect_cleanup;
1447
1448   /* Primary tunnel socket endpoints are now connected. Tunnel data back and
1449      forth over the primary tunnel until client or server breaks the primary
1450      tunnel, simultaneously allowing establishment, operation and teardown of
1451      a secondary tunnel that may be used for passive FTP data connection. */
1452
1453   max_tunnel_idx = CTRL;
1454   primary = TRUE;
1455
1456   while(!got_exit_signal) {
1457
1458     fd_set input;
1459     fd_set output;
1460     struct timeval timeout = {0, 250000L}; /* 250 ms */
1461     ssize_t rc;
1462     curl_socket_t maxfd = (curl_socket_t)-1;
1463
1464     FD_ZERO(&input);
1465     FD_ZERO(&output);
1466
1467     if((clientfd[DATA] == CURL_SOCKET_BAD) &&
1468        (serverfd[DATA] == CURL_SOCKET_BAD) &&
1469        poll_client_rd[CTRL] && poll_client_wr[CTRL] &&
1470        poll_server_rd[CTRL] && poll_server_wr[CTRL]) {
1471       /* listener socket is monitored to allow client to establish
1472          secondary tunnel only when this tunnel is not established
1473          and primary one is fully operational */
1474       FD_SET(rootfd, &input);
1475       maxfd = rootfd;
1476     }
1477
1478     /* set tunnel sockets to wait for */
1479     for(i = 0; i <= max_tunnel_idx; i++) {
1480       /* client side socket monitoring */
1481       if(clientfd[i] != CURL_SOCKET_BAD) {
1482         if(poll_client_rd[i]) {
1483           /* unless told not to do so, monitor readability */
1484           FD_SET(clientfd[i], &input);
1485           if(clientfd[i] > maxfd)
1486             maxfd = clientfd[i];
1487         }
1488         if(poll_client_wr[i] && toc[i]) {
1489           /* unless told not to do so, monitor writeability
1490              if there is data ready to be sent to client */
1491           FD_SET(clientfd[i], &output);
1492           if(clientfd[i] > maxfd)
1493             maxfd = clientfd[i];
1494         }
1495       }
1496       /* server side socket monitoring */
1497       if(serverfd[i] != CURL_SOCKET_BAD) {
1498         if(poll_server_rd[i]) {
1499           /* unless told not to do so, monitor readability */
1500           FD_SET(serverfd[i], &input);
1501           if(serverfd[i] > maxfd)
1502             maxfd = serverfd[i];
1503         }
1504         if(poll_server_wr[i] && tos[i]) {
1505           /* unless told not to do so, monitor writeability
1506              if there is data ready to be sent to server */
1507           FD_SET(serverfd[i], &output);
1508           if(serverfd[i] > maxfd)
1509             maxfd = serverfd[i];
1510         }
1511       }
1512     }
1513     if(got_exit_signal)
1514       break;
1515
1516     rc = select((int)maxfd + 1, &input, &output, NULL, &timeout);
1517
1518     if(rc > 0) {
1519       /* socket action */
1520       bool tcp_fin_wr;
1521
1522       if(got_exit_signal)
1523         break;
1524
1525       tcp_fin_wr = FALSE;
1526
1527       /* ---------------------------------------------------------- */
1528
1529       /* passive mode FTP may establish a secondary tunnel */
1530       if((clientfd[DATA] == CURL_SOCKET_BAD) &&
1531          (serverfd[DATA] == CURL_SOCKET_BAD) && FD_ISSET(rootfd, &input)) {
1532         /* a new connection on listener socket (most likely from client) */
1533         curl_socket_t datafd = accept(rootfd, NULL, NULL);
1534         if(datafd != CURL_SOCKET_BAD) {
1535           struct httprequest req2;
1536           int err = 0;
1537           memset(&req2, 0, sizeof(req2));
1538           logmsg("====> Client connect DATA");
1539 #ifdef TCP_NODELAY
1540           if(socket_domain_is_ip()) {
1541             /* Disable the Nagle algorithm */
1542             curl_socklen_t flag = 1;
1543             if(0 != setsockopt(datafd, IPPROTO_TCP, TCP_NODELAY,
1544                                (void *)&flag, sizeof(flag)))
1545               logmsg("====> TCP_NODELAY for client DATA conection failed");
1546             else
1547               logmsg("TCP_NODELAY set for client DATA conection");
1548           }
1549 #endif
1550           req2.pipelining = FALSE;
1551           init_httprequest(&req2);
1552           while(!req2.done_processing) {
1553             err = get_request(datafd, &req2);
1554             if(err < 0) {
1555               /* this socket must be closed, done or not */
1556               break;
1557             }
1558           }
1559
1560           /* skip this and close the socket if err < 0 */
1561           if(err >= 0) {
1562             err = send_doc(datafd, &req2);
1563             if(!err && req2.connect_request) {
1564               /* sleep to prevent triggering libcurl known bug #39. */
1565               for(loop = 2; (loop > 0) && !got_exit_signal; loop--)
1566                 wait_ms(250);
1567               if(!got_exit_signal) {
1568                 /* connect to the server */
1569                 serverfd[DATA] = connect_to(ipaddr, req2.connect_port);
1570                 if(serverfd[DATA] != CURL_SOCKET_BAD) {
1571                   /* secondary tunnel established, now we have two connections */
1572                   poll_client_rd[DATA] = TRUE;
1573                   poll_client_wr[DATA] = TRUE;
1574                   poll_server_rd[DATA] = TRUE;
1575                   poll_server_wr[DATA] = TRUE;
1576                   max_tunnel_idx = DATA;
1577                   secondary = TRUE;
1578                   toc[DATA] = 0;
1579                   tos[DATA] = 0;
1580                   clientfd[DATA] = datafd;
1581                   datafd = CURL_SOCKET_BAD;
1582                 }
1583               }
1584             }
1585           }
1586           if(datafd != CURL_SOCKET_BAD) {
1587             /* secondary tunnel not established */
1588             shutdown(datafd, SHUT_RDWR);
1589             sclose(datafd);
1590           }
1591         }
1592         if(got_exit_signal)
1593           break;
1594       }
1595
1596       /* ---------------------------------------------------------- */
1597
1598       /* react to tunnel endpoint readable/writeable notifications */
1599       for(i = 0; i <= max_tunnel_idx; i++) {
1600         size_t len;
1601         if(clientfd[i] != CURL_SOCKET_BAD) {
1602           len = sizeof(readclient[i]) - tos[i];
1603           if(len && FD_ISSET(clientfd[i], &input)) {
1604             /* read from client */
1605             rc = sread(clientfd[i], &readclient[i][tos[i]], len);
1606             if(rc <= 0) {
1607               logmsg("[%s] got %zd, STOP READING client", data_or_ctrl(i), rc);
1608               shutdown(clientfd[i], SHUT_RD);
1609               poll_client_rd[i] = FALSE;
1610             }
1611             else {
1612               logmsg("[%s] READ %zd bytes from client", data_or_ctrl(i), rc);
1613               logmsg("[%s] READ \"%s\"", data_or_ctrl(i),
1614                      data_to_hex(&readclient[i][tos[i]], rc));
1615               tos[i] += rc;
1616             }
1617           }
1618         }
1619         if(serverfd[i] != CURL_SOCKET_BAD) {
1620           len = sizeof(readserver[i])-toc[i];
1621           if(len && FD_ISSET(serverfd[i], &input)) {
1622             /* read from server */
1623             rc = sread(serverfd[i], &readserver[i][toc[i]], len);
1624             if(rc <= 0) {
1625               logmsg("[%s] got %zd, STOP READING server", data_or_ctrl(i), rc);
1626               shutdown(serverfd[i], SHUT_RD);
1627               poll_server_rd[i] = FALSE;
1628             }
1629             else {
1630               logmsg("[%s] READ %zd bytes from server", data_or_ctrl(i), rc);
1631               logmsg("[%s] READ \"%s\"", data_or_ctrl(i),
1632                      data_to_hex(&readserver[i][toc[i]], rc));
1633               toc[i] += rc;
1634             }
1635           }
1636         }
1637         if(clientfd[i] != CURL_SOCKET_BAD) {
1638           if(toc[i] && FD_ISSET(clientfd[i], &output)) {
1639             /* write to client */
1640             rc = swrite(clientfd[i], readserver[i], toc[i]);
1641             if(rc <= 0) {
1642               logmsg("[%s] got %zd, STOP WRITING client", data_or_ctrl(i), rc);
1643               shutdown(clientfd[i], SHUT_WR);
1644               poll_client_wr[i] = FALSE;
1645               tcp_fin_wr = TRUE;
1646             }
1647             else {
1648               logmsg("[%s] SENT %zd bytes to client", data_or_ctrl(i), rc);
1649               logmsg("[%s] SENT \"%s\"", data_or_ctrl(i),
1650                      data_to_hex(readserver[i], rc));
1651               if(toc[i] - rc)
1652                 memmove(&readserver[i][0], &readserver[i][rc], toc[i]-rc);
1653               toc[i] -= rc;
1654             }
1655           }
1656         }
1657         if(serverfd[i] != CURL_SOCKET_BAD) {
1658           if(tos[i] && FD_ISSET(serverfd[i], &output)) {
1659             /* write to server */
1660             rc = swrite(serverfd[i], readclient[i], tos[i]);
1661             if(rc <= 0) {
1662               logmsg("[%s] got %zd, STOP WRITING server", data_or_ctrl(i), rc);
1663               shutdown(serverfd[i], SHUT_WR);
1664               poll_server_wr[i] = FALSE;
1665               tcp_fin_wr = TRUE;
1666             }
1667             else {
1668               logmsg("[%s] SENT %zd bytes to server", data_or_ctrl(i), rc);
1669               logmsg("[%s] SENT \"%s\"", data_or_ctrl(i),
1670                      data_to_hex(readclient[i], rc));
1671               if(tos[i] - rc)
1672                 memmove(&readclient[i][0], &readclient[i][rc], tos[i]-rc);
1673               tos[i] -= rc;
1674             }
1675           }
1676         }
1677       }
1678       if(got_exit_signal)
1679         break;
1680
1681       /* ---------------------------------------------------------- */
1682
1683       /* endpoint read/write disabling, endpoint closing and tunnel teardown */
1684       for(i = 0; i <= max_tunnel_idx; i++) {
1685         for(loop = 2; loop > 0; loop--) {
1686           /* loop twice to satisfy condition interdependencies without
1687              having to await select timeout or another socket event */
1688           if(clientfd[i] != CURL_SOCKET_BAD) {
1689             if(poll_client_rd[i] && !poll_server_wr[i]) {
1690               logmsg("[%s] DISABLED READING client", data_or_ctrl(i));
1691               shutdown(clientfd[i], SHUT_RD);
1692               poll_client_rd[i] = FALSE;
1693             }
1694             if(poll_client_wr[i] && !poll_server_rd[i] && !toc[i]) {
1695               logmsg("[%s] DISABLED WRITING client", data_or_ctrl(i));
1696               shutdown(clientfd[i], SHUT_WR);
1697               poll_client_wr[i] = FALSE;
1698               tcp_fin_wr = TRUE;
1699             }
1700           }
1701           if(serverfd[i] != CURL_SOCKET_BAD) {
1702             if(poll_server_rd[i] && !poll_client_wr[i]) {
1703               logmsg("[%s] DISABLED READING server", data_or_ctrl(i));
1704               shutdown(serverfd[i], SHUT_RD);
1705               poll_server_rd[i] = FALSE;
1706             }
1707             if(poll_server_wr[i] && !poll_client_rd[i] && !tos[i]) {
1708               logmsg("[%s] DISABLED WRITING server", data_or_ctrl(i));
1709               shutdown(serverfd[i], SHUT_WR);
1710               poll_server_wr[i] = FALSE;
1711               tcp_fin_wr = TRUE;
1712             }
1713           }
1714         }
1715       }
1716
1717       if(tcp_fin_wr)
1718         /* allow kernel to place FIN bit packet on the wire */
1719         wait_ms(250);
1720
1721       /* socket clearing */
1722       for(i = 0; i <= max_tunnel_idx; i++) {
1723         for(loop = 2; loop > 0; loop--) {
1724           if(clientfd[i] != CURL_SOCKET_BAD) {
1725             if(!poll_client_wr[i] && !poll_client_rd[i]) {
1726               logmsg("[%s] CLOSING client socket", data_or_ctrl(i));
1727               sclose(clientfd[i]);
1728               clientfd[i] = CURL_SOCKET_BAD;
1729               if(serverfd[i] == CURL_SOCKET_BAD) {
1730                 logmsg("[%s] ENDING", data_or_ctrl(i));
1731                 if(i == DATA)
1732                   secondary = FALSE;
1733                 else
1734                   primary = FALSE;
1735               }
1736             }
1737           }
1738           if(serverfd[i] != CURL_SOCKET_BAD) {
1739             if(!poll_server_wr[i] && !poll_server_rd[i]) {
1740               logmsg("[%s] CLOSING server socket", data_or_ctrl(i));
1741               sclose(serverfd[i]);
1742               serverfd[i] = CURL_SOCKET_BAD;
1743               if(clientfd[i] == CURL_SOCKET_BAD) {
1744                 logmsg("[%s] ENDING", data_or_ctrl(i));
1745                 if(i == DATA)
1746                   secondary = FALSE;
1747                 else
1748                   primary = FALSE;
1749               }
1750             }
1751           }
1752         }
1753       }
1754
1755       /* ---------------------------------------------------------- */
1756
1757       max_tunnel_idx = secondary ? DATA : CTRL;
1758
1759       if(!primary)
1760         /* exit loop upon primary tunnel teardown */
1761         break;
1762
1763     } /* (rc > 0) */
1764
1765   }
1766
1767 http_connect_cleanup:
1768
1769   for(i = DATA; i >= CTRL; i--) {
1770     if(serverfd[i] != CURL_SOCKET_BAD) {
1771       logmsg("[%s] CLOSING server socket (cleanup)", data_or_ctrl(i));
1772       shutdown(serverfd[i], SHUT_RDWR);
1773       sclose(serverfd[i]);
1774     }
1775     if(clientfd[i] != CURL_SOCKET_BAD) {
1776       logmsg("[%s] CLOSING client socket (cleanup)", data_or_ctrl(i));
1777       shutdown(clientfd[i], SHUT_RDWR);
1778       sclose(clientfd[i]);
1779     }
1780     if((serverfd[i] != CURL_SOCKET_BAD) ||
1781        (clientfd[i] != CURL_SOCKET_BAD)) {
1782       logmsg("[%s] ABORTING", data_or_ctrl(i));
1783     }
1784   }
1785
1786   *infdp = CURL_SOCKET_BAD;
1787 }
1788
1789 static void http2(struct httprequest *req)
1790 {
1791   (void)req;
1792   logmsg("switched to http2");
1793   /* left to implement */
1794 }
1795
1796
1797 /* returns a socket handle, or 0 if there are no more waiting sockets,
1798    or < 0 if there was an error */
1799 static curl_socket_t accept_connection(curl_socket_t sock)
1800 {
1801   curl_socket_t msgsock = CURL_SOCKET_BAD;
1802   int error;
1803   int flag = 1;
1804
1805   if(MAX_SOCKETS == num_sockets) {
1806     logmsg("Too many open sockets!");
1807     return CURL_SOCKET_BAD;
1808   }
1809
1810   msgsock = accept(sock, NULL, NULL);
1811
1812   if(got_exit_signal) {
1813     if(CURL_SOCKET_BAD != msgsock)
1814       sclose(msgsock);
1815     return CURL_SOCKET_BAD;
1816   }
1817
1818   if(CURL_SOCKET_BAD == msgsock) {
1819     error = SOCKERRNO;
1820     if(EAGAIN == error || EWOULDBLOCK == error) {
1821       /* nothing to accept */
1822       return 0;
1823     }
1824     logmsg("MAJOR ERROR: accept() failed with error: (%d) %s",
1825            error, strerror(error));
1826     return CURL_SOCKET_BAD;
1827   }
1828
1829   if(0 != curlx_nonblock(msgsock, TRUE)) {
1830     error = SOCKERRNO;
1831     logmsg("curlx_nonblock failed with error: (%d) %s",
1832            error, strerror(error));
1833     sclose(msgsock);
1834     return CURL_SOCKET_BAD;
1835   }
1836
1837   if(0 != setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE,
1838                      (void *)&flag, sizeof(flag))) {
1839     error = SOCKERRNO;
1840     logmsg("setsockopt(SO_KEEPALIVE) failed with error: (%d) %s",
1841            error, strerror(error));
1842     sclose(msgsock);
1843     return CURL_SOCKET_BAD;
1844   }
1845
1846   /*
1847   ** As soon as this server accepts a connection from the test harness it
1848   ** must set the server logs advisor read lock to indicate that server
1849   ** logs should not be read until this lock is removed by this server.
1850   */
1851
1852   if(!serverlogslocked)
1853     set_advisor_read_lock(SERVERLOGS_LOCK);
1854   serverlogslocked += 1;
1855
1856   logmsg("====> Client connect");
1857
1858   all_sockets[num_sockets] = msgsock;
1859   num_sockets += 1;
1860
1861 #ifdef TCP_NODELAY
1862   if(socket_domain_is_ip()) {
1863     /*
1864      * Disable the Nagle algorithm to make it easier to send out a large
1865      * response in many small segments to torture the clients more.
1866      */
1867     if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
1868                        (void *)&flag, sizeof(flag)))
1869       logmsg("====> TCP_NODELAY failed");
1870     else
1871       logmsg("TCP_NODELAY set");
1872   }
1873 #endif
1874
1875   return msgsock;
1876 }
1877
1878 /* returns 1 if the connection should be serviced again immediately, 0 if there
1879    is no data waiting, or < 0 if it should be closed */
1880 static int service_connection(curl_socket_t msgsock, struct httprequest *req,
1881                               curl_socket_t listensock,
1882                               const char *connecthost)
1883 {
1884   if(got_exit_signal)
1885     return -1;
1886
1887   while(!req->done_processing) {
1888     int rc = get_request(msgsock, req);
1889     if (rc <= 0) {
1890       /* Nothing further to read now (possibly because the socket was closed */
1891       return rc;
1892     }
1893   }
1894
1895   if(prevbounce) {
1896     /* bounce treatment requested */
1897     if((req->testno == prevtestno) &&
1898        (req->partno == prevpartno)) {
1899       req->partno++;
1900       logmsg("BOUNCE part number to %ld", req->partno);
1901     }
1902     else {
1903       prevbounce = FALSE;
1904       prevtestno = -1;
1905       prevpartno = -1;
1906     }
1907   }
1908
1909   send_doc(msgsock, req);
1910   if(got_exit_signal)
1911     return -1;
1912
1913   if(req->testno < 0) {
1914     logmsg("special request received, no persistency");
1915     return -1;
1916   }
1917   if(!req->open) {
1918     logmsg("instructed to close connection after server-reply");
1919     return -1;
1920   }
1921
1922   if(req->connect_request) {
1923     /* a CONNECT request, setup and talk the tunnel */
1924     if(!is_proxy) {
1925       logmsg("received CONNECT but isn't running as proxy!");
1926       return 1;
1927     }
1928     else {
1929       http_connect(&msgsock, listensock, connecthost, req->connect_port);
1930       return -1;
1931     }
1932   }
1933
1934   if(req->upgrade_request) {
1935     /* an upgrade request, switch to http2 here */
1936     http2(req);
1937     return -1;
1938   }
1939
1940   /* if we got a CONNECT, loop and get another request as well! */
1941
1942   if(req->open) {
1943     logmsg("=> persistant connection request ended, awaits new request\n");
1944     return 1;
1945   }
1946
1947   return -1;
1948 }
1949
1950 int main(int argc, char *argv[])
1951 {
1952   srvr_sockaddr_union_t me;
1953   curl_socket_t sock = CURL_SOCKET_BAD;
1954   int wrotepidfile = 0;
1955   int flag;
1956   unsigned short port = DEFAULT_PORT;
1957 #ifdef USE_UNIX_SOCKETS
1958   const char *unix_socket = NULL;
1959   bool unlink_socket = false;
1960 #endif
1961   char *pidname= (char *)".http.pid";
1962   struct httprequest req;
1963   int rc = 0;
1964   int error;
1965   int arg=1;
1966   long pid;
1967   const char *connecthost = "127.0.0.1";
1968   const char *socket_type = "IPv4";
1969   char port_str[11];
1970   const char *location_str = port_str;
1971
1972   /* a default CONNECT port is basically pointless but still ... */
1973   size_t socket_idx;
1974
1975   memset(&req, 0, sizeof(req));
1976
1977   while(argc>arg) {
1978     if(!strcmp("--version", argv[arg])) {
1979       puts("sws IPv4"
1980 #ifdef ENABLE_IPV6
1981              "/IPv6"
1982 #endif
1983 #ifdef USE_UNIX_SOCKETS
1984              "/unix"
1985 #endif
1986           );
1987       return 0;
1988     }
1989     else if(!strcmp("--pidfile", argv[arg])) {
1990       arg++;
1991       if(argc>arg)
1992         pidname = argv[arg++];
1993     }
1994     else if(!strcmp("--logfile", argv[arg])) {
1995       arg++;
1996       if(argc>arg)
1997         serverlogfile = argv[arg++];
1998     }
1999     else if(!strcmp("--gopher", argv[arg])) {
2000       arg++;
2001       use_gopher = TRUE;
2002       end_of_headers = "\r\n"; /* gopher style is much simpler */
2003     }
2004     else if(!strcmp("--ipv4", argv[arg])) {
2005       socket_type = "IPv4";
2006       socket_domain = AF_INET;
2007       location_str = port_str;
2008       arg++;
2009     }
2010     else if(!strcmp("--ipv6", argv[arg])) {
2011 #ifdef ENABLE_IPV6
2012       socket_type = "IPv6";
2013       socket_domain = AF_INET6;
2014       location_str = port_str;
2015 #endif
2016       arg++;
2017     }
2018     else if(!strcmp("--unix-socket", argv[arg])) {
2019       arg++;
2020       if(argc>arg) {
2021 #ifdef USE_UNIX_SOCKETS
2022         unix_socket = argv[arg];
2023         if(strlen(unix_socket) >= sizeof(me.sau.sun_path)) {
2024           fprintf(stderr, "sws: socket path must be shorter than %zu chars\n",
2025                   sizeof(me.sau.sun_path));
2026           return 0;
2027         }
2028         socket_type = "unix";
2029         socket_domain = AF_UNIX;
2030         location_str = unix_socket;
2031 #endif
2032         arg++;
2033       }
2034     }
2035     else if(!strcmp("--port", argv[arg])) {
2036       arg++;
2037       if(argc>arg) {
2038         char *endptr;
2039         unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
2040         if((endptr != argv[arg] + strlen(argv[arg])) ||
2041            (ulnum < 1025UL) || (ulnum > 65535UL)) {
2042           fprintf(stderr, "sws: invalid --port argument (%s)\n",
2043                   argv[arg]);
2044           return 0;
2045         }
2046         port = curlx_ultous(ulnum);
2047         arg++;
2048       }
2049     }
2050     else if(!strcmp("--srcdir", argv[arg])) {
2051       arg++;
2052       if(argc>arg) {
2053         path = argv[arg];
2054         arg++;
2055       }
2056     }
2057     else if(!strcmp("--connect", argv[arg])) {
2058       /* The connect host IP number that the proxy will connect to no matter
2059          what the client asks for, but also use this as a hint that we run as
2060          a proxy and do a few different internal choices */
2061       arg++;
2062       if(argc>arg) {
2063         connecthost = argv[arg];
2064         arg++;
2065         is_proxy = TRUE;
2066         logmsg("Run as proxy, CONNECT to host %s", connecthost);
2067       }
2068     }
2069     else {
2070       puts("Usage: sws [option]\n"
2071            " --version\n"
2072            " --logfile [file]\n"
2073            " --pidfile [file]\n"
2074            " --ipv4\n"
2075            " --ipv6\n"
2076            " --unix-socket [file]\n"
2077            " --port [port]\n"
2078            " --srcdir [path]\n"
2079            " --connect [ip4-addr]\n"
2080            " --gopher");
2081       return 0;
2082     }
2083   }
2084
2085   snprintf(port_str, sizeof(port_str), "port %hu", port);
2086
2087 #ifdef WIN32
2088   win32_init();
2089   atexit(win32_cleanup);
2090 #endif
2091
2092   install_signal_handlers();
2093
2094   pid = (long)getpid();
2095
2096   sock = socket(socket_domain, SOCK_STREAM, 0);
2097
2098   all_sockets[0] = sock;
2099   num_sockets = 1;
2100
2101   if(CURL_SOCKET_BAD == sock) {
2102     error = SOCKERRNO;
2103     logmsg("Error creating socket: (%d) %s",
2104            error, strerror(error));
2105     goto sws_cleanup;
2106   }
2107
2108   flag = 1;
2109   if(0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
2110                      (void *)&flag, sizeof(flag))) {
2111     error = SOCKERRNO;
2112     logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
2113            error, strerror(error));
2114     goto sws_cleanup;
2115   }
2116   if(0 != curlx_nonblock(sock, TRUE)) {
2117     error = SOCKERRNO;
2118     logmsg("curlx_nonblock failed with error: (%d) %s",
2119            error, strerror(error));
2120     goto sws_cleanup;
2121   }
2122
2123   switch(socket_domain) {
2124   case AF_INET:
2125     memset(&me.sa4, 0, sizeof(me.sa4));
2126     me.sa4.sin_family = AF_INET;
2127     me.sa4.sin_addr.s_addr = INADDR_ANY;
2128     me.sa4.sin_port = htons(port);
2129     rc = bind(sock, &me.sa, sizeof(me.sa4));
2130     break;
2131 #ifdef ENABLE_IPV6
2132   case AF_INET6:
2133     memset(&me.sa6, 0, sizeof(me.sa6));
2134     me.sa6.sin6_family = AF_INET6;
2135     me.sa6.sin6_addr = in6addr_any;
2136     me.sa6.sin6_port = htons(port);
2137     rc = bind(sock, &me.sa, sizeof(me.sa6));
2138     break;
2139 #endif /* ENABLE_IPV6 */
2140 #ifdef USE_UNIX_SOCKETS
2141   case AF_UNIX:
2142     memset(&me.sau, 0, sizeof(me.sau));
2143     me.sau.sun_family = AF_UNIX;
2144     strncpy(me.sau.sun_path, unix_socket, sizeof(me.sau.sun_path));
2145     rc = bind(sock, &me.sa, sizeof(me.sau));
2146     if(0 != rc && errno == EADDRINUSE) {
2147       struct stat statbuf;
2148       /* socket already exists. Perhaps it is stale? */
2149       int unixfd = socket(AF_UNIX, SOCK_STREAM, 0);
2150       if(CURL_SOCKET_BAD == unixfd) {
2151         error = SOCKERRNO;
2152         logmsg("Error binding socket, failed to create socket at %s: (%d) %s",
2153                unix_socket, error, strerror(error));
2154         goto sws_cleanup;
2155       }
2156       /* check whether the server is alive */
2157       rc = connect(unixfd, &me.sa, sizeof(me.sau));
2158       error = errno;
2159       close(unixfd);
2160       if(ECONNREFUSED != error) {
2161         logmsg("Error binding socket, failed to connect to %s: (%d) %s",
2162                unix_socket, error, strerror(error));
2163         goto sws_cleanup;
2164       }
2165       /* socket server is not alive, now check if it was actually a socket.
2166        * Systems which have Unix sockets will also have lstat */
2167       rc = lstat(unix_socket, &statbuf);
2168       if (0 != rc) {
2169         logmsg("Error binding socket, failed to stat %s: (%d) %s",
2170                unix_socket, errno, strerror(errno));
2171         goto sws_cleanup;
2172       }
2173       if((statbuf.st_mode & S_IFSOCK) != S_IFSOCK) {
2174         logmsg("Error binding socket, failed to stat %s: (%d) %s",
2175                unix_socket, error, strerror(error));
2176         goto sws_cleanup;
2177       }
2178       /* dead socket, cleanup and retry bind */
2179       rc = unlink(unix_socket);
2180       if(0 != rc) {
2181         logmsg("Error binding socket, failed to unlink %s: (%d) %s",
2182                unix_socket, errno, strerror(errno));
2183         goto sws_cleanup;
2184       }
2185       /* stale socket is gone, retry bind */
2186       rc = bind(sock, &me.sa, sizeof(me.sau));
2187     }
2188     break;
2189 #endif /* USE_UNIX_SOCKETS */
2190   }
2191   if(0 != rc) {
2192     error = SOCKERRNO;
2193     logmsg("Error binding socket on %s: (%d) %s",
2194            location_str, error, strerror(error));
2195     goto sws_cleanup;
2196   }
2197
2198   logmsg("Running %s %s version on %s",
2199          use_gopher?"GOPHER":"HTTP", socket_type, location_str);
2200
2201   /* start accepting connections */
2202   rc = listen(sock, 5);
2203   if(0 != rc) {
2204     error = SOCKERRNO;
2205     logmsg("listen() failed with error: (%d) %s",
2206            error, strerror(error));
2207     goto sws_cleanup;
2208   }
2209
2210 #ifdef USE_UNIX_SOCKETS
2211   /* listen succeeds, so let's assume a valid listening Unix socket */
2212   unlink_socket = true;
2213 #endif
2214
2215   /*
2216   ** As soon as this server writes its pid file the test harness will
2217   ** attempt to connect to this server and initiate its verification.
2218   */
2219
2220   wrotepidfile = write_pidfile(pidname);
2221   if(!wrotepidfile)
2222     goto sws_cleanup;
2223
2224   /* initialization of httprequest struct is done before get_request(), but
2225      the pipelining struct field must be initialized previously to FALSE
2226      every time a new connection arrives. */
2227
2228   req.pipelining = FALSE;
2229   init_httprequest(&req);
2230
2231   for(;;) {
2232     fd_set input;
2233     fd_set output;
2234     struct timeval timeout = {0, 250000L}; /* 250 ms */
2235     curl_socket_t maxfd = (curl_socket_t)-1;
2236
2237     /* Clear out closed sockets */
2238     for (socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) {
2239       if (CURL_SOCKET_BAD == all_sockets[socket_idx]) {
2240         char* dst = (char *) (all_sockets + socket_idx);
2241         char* src = (char *) (all_sockets + socket_idx + 1);
2242         char* end = (char *) (all_sockets + num_sockets);
2243         memmove(dst, src, end - src);
2244         num_sockets -= 1;
2245       }
2246     }
2247
2248     if(got_exit_signal)
2249       goto sws_cleanup;
2250
2251     /* Set up for select*/
2252     FD_ZERO(&input);
2253     FD_ZERO(&output);
2254
2255     for (socket_idx = 0; socket_idx < num_sockets; ++socket_idx) {
2256       /* Listen on all sockets */
2257       FD_SET(all_sockets[socket_idx], &input);
2258       if(all_sockets[socket_idx] > maxfd)
2259         maxfd = all_sockets[socket_idx];
2260     }
2261
2262     if(got_exit_signal)
2263       goto sws_cleanup;
2264
2265     rc = select((int)maxfd + 1, &input, &output, NULL, &timeout);
2266     if (rc < 0) {
2267       error = SOCKERRNO;
2268       logmsg("select() failed with error: (%d) %s",
2269              error, strerror(error));
2270       goto sws_cleanup;
2271     }
2272
2273     if(got_exit_signal)
2274       goto sws_cleanup;
2275
2276     if (rc == 0) {
2277       /* Timed out - try again*/
2278       continue;
2279     }
2280
2281     /* Check if the listening socket is ready to accept */
2282     if (FD_ISSET(all_sockets[0], &input)) {
2283       /* Service all queued connections */
2284       curl_socket_t msgsock;
2285       do {
2286         msgsock = accept_connection(sock);
2287         logmsg("accept_connection %d returned %d", sock, msgsock);
2288         if (CURL_SOCKET_BAD == msgsock)
2289           goto sws_cleanup;
2290       } while (msgsock > 0);
2291     }
2292
2293     /* Service all connections that are ready */
2294     for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx) {
2295       if (FD_ISSET(all_sockets[socket_idx], &input)) {
2296         if(got_exit_signal)
2297           goto sws_cleanup;
2298
2299         /* Service this connection until it has nothing available */
2300         do {
2301           rc = service_connection(all_sockets[socket_idx], &req, sock,
2302                                   connecthost);
2303           if(got_exit_signal)
2304             goto sws_cleanup;
2305
2306           if (rc < 0) {
2307             logmsg("====> Client disconnect %d", req.connmon);
2308
2309             if(req.connmon) {
2310               const char *keepopen="[DISCONNECT]\n";
2311               storerequest((char *)keepopen, strlen(keepopen));
2312             }
2313
2314             if(!req.open)
2315               /* When instructed to close connection after server-reply we
2316                  wait a very small amount of time before doing so. If this
2317                  is not done client might get an ECONNRESET before reading
2318                  a single byte of server-reply. */
2319               wait_ms(50);
2320
2321             if(all_sockets[socket_idx] != CURL_SOCKET_BAD) {
2322               sclose(all_sockets[socket_idx]);
2323               all_sockets[socket_idx] = CURL_SOCKET_BAD;
2324             }
2325
2326             serverlogslocked -= 1;
2327             if(!serverlogslocked)
2328               clear_advisor_read_lock(SERVERLOGS_LOCK);
2329
2330             if (req.testno == DOCNUMBER_QUIT)
2331               goto sws_cleanup;
2332           }
2333
2334           /* Reset the request, unless we're still in the middle of reading */
2335           if (rc != 0)
2336             init_httprequest(&req);
2337         } while (rc > 0);
2338       }
2339     }
2340
2341     if(got_exit_signal)
2342       goto sws_cleanup;
2343   }
2344
2345 sws_cleanup:
2346
2347   for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx)
2348     if((all_sockets[socket_idx] != sock) &&
2349      (all_sockets[socket_idx] != CURL_SOCKET_BAD))
2350       sclose(all_sockets[socket_idx]);
2351
2352   if(sock != CURL_SOCKET_BAD)
2353     sclose(sock);
2354
2355 #ifdef USE_UNIX_SOCKETS
2356   if(unlink_socket && socket_domain == AF_UNIX) {
2357     rc = unlink(unix_socket);
2358     logmsg("unlink(%s) = %d (%s)", unix_socket, rc, strerror(rc));
2359   }
2360 #endif
2361
2362   if(got_exit_signal)
2363     logmsg("signalled to die");
2364
2365   if(wrotepidfile)
2366     unlink(pidname);
2367
2368   if(serverlogslocked) {
2369     serverlogslocked = 0;
2370     clear_advisor_read_lock(SERVERLOGS_LOCK);
2371   }
2372
2373   restore_signal_handlers();
2374
2375   if(got_exit_signal) {
2376     logmsg("========> %s sws (%s pid: %ld) exits with signal (%d)",
2377            socket_type, location_str, pid, exit_signal);
2378     /*
2379      * To properly set the return status of the process we
2380      * must raise the same signal SIGINT or SIGTERM that we
2381      * caught and let the old handler take care of it.
2382      */
2383     raise(exit_signal);
2384   }
2385
2386   logmsg("========> sws quits");
2387   return 0;
2388 }
2389