Imported Upstream version 7.53.1
[platform/upstream/curl.git] / tests / server / sws.c
index 8cd30c5..5646f96 100644 (file)
@@ -5,11 +5,11 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
  *
  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  * copies of the Software, and permit persons to whom the Software is
@@ -140,7 +140,7 @@ static void storerequest(char *reqbuf, size_t totalsize);
 
 const char *serverlogfile = DEFAULT_LOGFILE;
 
-#define SWSVERSION "cURL test suite HTTP server/0.1"
+#define SWSVERSION "curl test suite HTTP server/0.1"
 
 #define REQUEST_DUMP  "log/server.input"
 #define RESPONSE_DUMP "log/server.response"
@@ -265,36 +265,42 @@ static void install_signal_handlers(void)
 {
 #ifdef SIGHUP
   /* ignore SIGHUP signal */
-  if((old_sighup_handler = signal(SIGHUP, SIG_IGN)) == SIG_ERR)
+  old_sighup_handler = signal(SIGHUP, SIG_IGN);
+  if(old_sighup_handler == SIG_ERR)
     logmsg("cannot install SIGHUP handler: %s", strerror(errno));
 #endif
 #ifdef SIGPIPE
   /* ignore SIGPIPE signal */
-  if((old_sigpipe_handler = signal(SIGPIPE, SIG_IGN)) == SIG_ERR)
+  old_sigpipe_handler = signal(SIGPIPE, SIG_IGN);
+  if(old_sigpipe_handler == SIG_ERR)
     logmsg("cannot install SIGPIPE handler: %s", strerror(errno));
 #endif
 #ifdef SIGALRM
   /* ignore SIGALRM signal */
-  if((old_sigalrm_handler = signal(SIGALRM, SIG_IGN)) == SIG_ERR)
+  old_sigalrm_handler = signal(SIGALRM, SIG_IGN);
+  if(old_sigalrm_handler == SIG_ERR)
     logmsg("cannot install SIGALRM handler: %s", strerror(errno));
 #endif
 #ifdef SIGINT
   /* handle SIGINT signal with our exit_signal_handler */
-  if((old_sigint_handler = signal(SIGINT, exit_signal_handler)) == SIG_ERR)
+  old_sigint_handler = signal(SIGINT, exit_signal_handler);
+  if(old_sigint_handler == SIG_ERR)
     logmsg("cannot install SIGINT handler: %s", strerror(errno));
   else
     siginterrupt(SIGINT, 1);
 #endif
 #ifdef SIGTERM
   /* handle SIGTERM signal with our exit_signal_handler */
-  if((old_sigterm_handler = signal(SIGTERM, exit_signal_handler)) == SIG_ERR)
+  old_sigterm_handler = signal(SIGTERM, exit_signal_handler);
+  if(old_sigterm_handler == SIG_ERR)
     logmsg("cannot install SIGTERM handler: %s", strerror(errno));
   else
     siginterrupt(SIGTERM, 1);
 #endif
 #if defined(SIGBREAK) && defined(WIN32)
   /* handle SIGBREAK signal with our exit_signal_handler */
-  if((old_sigbreak_handler = signal(SIGBREAK, exit_signal_handler)) == SIG_ERR)
+  old_sigbreak_handler = signal(SIGBREAK, exit_signal_handler);
+  if(old_sigbreak_handler == SIG_ERR)
     logmsg("cannot install SIGBREAK handler: %s", strerror(errno));
   else
     siginterrupt(SIGBREAK, 1);
@@ -442,8 +448,7 @@ static int parse_servercmd(struct httprequest *req)
       else
         break;
     }
-    if(orgcmd)
-      free(orgcmd);
+    free(orgcmd);
   }
 
   return 0; /* OK! */
@@ -492,11 +497,11 @@ static int ProcessRequest(struct httprequest *req)
     /* get the number after it */
     if(ptr) {
       if((strlen(doc) + strlen(request)) < 400)
-        sprintf(logbuf, "Got request: %s %s HTTP/%d.%d",
-                request, doc, prot_major, prot_minor);
+        snprintf(logbuf, sizeof(logbuf), "Got request: %s %s HTTP/%d.%d",
+                 request, doc, prot_major, prot_minor);
       else
-        sprintf(logbuf, "Got a *HUGE* request HTTP/%d.%d",
-                prot_major, prot_minor);
+        snprintf(logbuf, sizeof(logbuf), "Got a *HUGE* request HTTP/%d.%d",
+                 prot_major, prot_minor);
       logmsg("%s", logbuf);
 
       if(!strncmp("/verifiedserver", ptr, 15)) {
@@ -528,8 +533,8 @@ static int ProcessRequest(struct httprequest *req)
 
       if(req->testno) {
 
-        sprintf(logbuf, "Requested test number %ld part %ld",
-                req->testno, req->partno);
+        snprintf(logbuf, sizeof(logbuf), "Requested test number %ld part %ld",
+                 req->testno, req->partno);
         logmsg("%s", logbuf);
 
         /* find and parse <servercmd> for this test */
@@ -549,8 +554,9 @@ static int ProcessRequest(struct httprequest *req)
         char *portp = NULL;
         unsigned long part=0;
 
-        sprintf(logbuf, "Received a CONNECT %s HTTP/%d.%d request",
-                doc, prot_major, prot_minor);
+        snprintf(logbuf, sizeof(logbuf),
+                 "Received a CONNECT %s HTTP/%d.%d request",
+                 doc, prot_major, prot_minor);
         logmsg("%s", logbuf);
 
         req->connect_request = TRUE;
@@ -572,7 +578,7 @@ static int ProcessRequest(struct httprequest *req)
           }
           if(*p != ']')
             logmsg("Invalid CONNECT IPv6 address format");
-          else if (*(p+1) != ':')
+          else if(*(p+1) != ':')
             logmsg("Invalid CONNECT IPv6 port format");
           else
             portp = p+1;
@@ -619,8 +625,9 @@ static int ProcessRequest(struct httprequest *req)
         else
           req->partno = 0;
 
-        sprintf(logbuf, "Requested test number %ld part %ld (from host name)",
-                req->testno, req->partno);
+        snprintf(logbuf, sizeof(logbuf),
+                 "Requested test number %ld part %ld (from host name)",
+                 req->testno, req->partno);
         logmsg("%s", logbuf);
 
       }
@@ -669,8 +676,9 @@ static int ProcessRequest(struct httprequest *req)
       else
         req->partno = 0;
 
-      sprintf(logbuf, "Requested GOPHER test number %ld part %ld",
-              req->testno, req->partno);
+      snprintf(logbuf, sizeof(logbuf),
+               "Requested GOPHER test number %ld part %ld",
+               req->testno, req->partno);
       logmsg("%s", logbuf);
     }
   }
@@ -695,7 +703,7 @@ static int ProcessRequest(struct httprequest *req)
     if(got_exit_signal)
       return 1; /* done */
 
-    if((req->cl==0) && curlx_strnequal("Content-Length:", line, 15)) {
+    if((req->cl==0) && strncasecompare("Content-Length:", line, 15)) {
       /* If we don't ignore content-length, we read it and we read the whole
          request including the body before we return. If we've been told to
          ignore the content-length, we will return as soon as all headers
@@ -721,7 +729,7 @@ static int ProcessRequest(struct httprequest *req)
         logmsg("... but will abort after %zu bytes", req->cl);
       break;
     }
-    else if(curlx_strnequal("Transfer-Encoding: chunked", line,
+    else if(strncasecompare("Transfer-Encoding: chunked", line,
                             strlen("Transfer-Encoding: chunked"))) {
       /* chunked data coming in */
       chunked = TRUE;
@@ -844,15 +852,15 @@ static void storerequest(char *reqbuf, size_t totalsize)
   FILE *dump;
   const char *dumpfile=is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP;
 
-  if (reqbuf == NULL)
+  if(reqbuf == NULL)
     return;
-  if (totalsize == 0)
+  if(totalsize == 0)
     return;
 
   do {
     dump = fopen(dumpfile, "ab");
-  } while ((dump == NULL) && ((error = errno) == EINTR));
-  if (dump == NULL) {
+  } while((dump == NULL) && ((error = errno) == EINTR));
+  if(dump == NULL) {
     logmsg("[2] Error opening file %s error: %d %s",
            dumpfile, error, strerror(error));
     logmsg("Failed to write request input ");
@@ -867,7 +875,7 @@ static void storerequest(char *reqbuf, size_t totalsize)
       goto storerequest_cleanup;
     if(written > 0)
       writeleft -= written;
-  } while ((writeleft > 0) && ((error = errno) == EINTR));
+  } while((writeleft > 0) && ((error = errno) == EINTR));
 
   if(writeleft == 0)
     logmsg("Wrote request (%zu bytes) input to %s", totalsize, dumpfile);
@@ -914,6 +922,8 @@ static void init_httprequest(struct httprequest *req)
   req->callcount = 0;
   req->connect_port = 0;
   req->done_processing = 0;
+  req->upgrade = 0;
+  req->upgrade_request = 0;
 }
 
 /* returns 1 if the connection should be serviced again immediately, 0 if there
@@ -967,7 +977,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
     }
     else if(got < 0) {
       error = SOCKERRNO;
-      if (EAGAIN == error || EWOULDBLOCK == error) {
+      if(EAGAIN == error || EWOULDBLOCK == error) {
         /* nothing to read at the moment */
         return 0;
       }
@@ -1012,7 +1022,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
     reqbuf[req->offset] = '\0';
 
   /* at the end of a request dump it to an external file */
-  if (fail || req->done_processing)
+  if(fail || req->done_processing)
     storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
   if(got_exit_signal)
     return -1;
@@ -1046,7 +1056,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
   case RCMD_STREAM:
 #define STREAMTHIS "a string to stream 01234567890\n"
     count = strlen(STREAMTHIS);
-    for (;;) {
+    for(;;) {
       written = swrite(sock, STREAMTHIS, count);
       if(got_exit_signal)
         return -1;
@@ -1075,13 +1085,14 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
     case DOCNUMBER_WERULEZ:
       /* we got a "friends?" question, reply back that we sure are */
       logmsg("Identifying ourselves as friends");
-      sprintf(msgbuf, "WE ROOLZ: %ld\r\n", (long)getpid());
+      snprintf(msgbuf, sizeof(msgbuf), "WE ROOLZ: %ld\r\n", (long)getpid());
       msglen = strlen(msgbuf);
       if(use_gopher)
-        sprintf(weare, "%s", msgbuf);
+        snprintf(weare, sizeof(weare), "%s", msgbuf);
       else
-        sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
-                msglen, msgbuf);
+        snprintf(weare, sizeof(weare),
+                 "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
+                 msglen, msgbuf);
       buffer = weare;
       break;
     case DOCNUMBER_404:
@@ -1102,9 +1113,9 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
     const char *section= req->connect_request?"connect":"data";
 
     if(req->partno)
-      sprintf(partbuf, "%s%ld", section, req->partno);
+      snprintf(partbuf, sizeof(partbuf), "%s%ld", section, req->partno);
     else
-      sprintf(partbuf, "%s", section);
+      snprintf(partbuf, sizeof(partbuf), "%s", section);
 
     logmsg("Send response test%ld section <%s>", req->testno, partbuf);
 
@@ -1126,8 +1137,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
     }
 
     if(got_exit_signal) {
-      if(ptr)
-        free(ptr);
+      free(ptr);
       return -1;
     }
 
@@ -1137,8 +1147,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
       error = errno;
       logmsg("fopen() failed with error: %d %s", error, strerror(error));
       logmsg("  [4] Error opening file: %s", filename);
-      if(ptr)
-        free(ptr);
+      free(ptr);
       return 0;
     }
     else {
@@ -1147,18 +1156,15 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
       fclose(stream);
       if(error) {
         logmsg("getpart() failed with error: %d", error);
-        if(ptr)
-          free(ptr);
+        free(ptr);
         return 0;
       }
     }
   }
 
   if(got_exit_signal) {
-    if(ptr)
-      free(ptr);
-    if(cmd)
-      free(cmd);
+    free(ptr);
+    free(cmd);
     return -1;
   }
 
@@ -1181,10 +1187,8 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
     error = errno;
     logmsg("fopen() failed with error: %d %s", error, strerror(error));
     logmsg("  [5] Error opening file: %s", responsedump);
-    if(ptr)
-      free(ptr);
-    if(cmd)
-      free(cmd);
+    free(ptr);
+    free(cmd);
     return -1;
   }
 
@@ -1196,14 +1200,21 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
     size_t num = count;
     if(num > 200)
       num = 200;
+
+    retry:
     written = swrite(sock, buffer, num);
-    if (written < 0) {
+    if(written < 0) {
+      if((EWOULDBLOCK == SOCKERRNO) || (EAGAIN == SOCKERRNO)) {
+        wait_ms(10);
+        goto retry;
+      }
       sendfailure = TRUE;
       break;
     }
     else {
       logmsg("Sent off %zd bytes", written);
     }
+
     /* write to file as well */
     fwrite(buffer, 1, (size_t)written, dump);
 
@@ -1228,30 +1239,25 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
            responsedump, error, strerror(error));
 
   if(got_exit_signal) {
-    if(ptr)
-      free(ptr);
-    if(cmd)
-      free(cmd);
+    free(ptr);
+    free(cmd);
     return -1;
   }
 
   if(sendfailure) {
-    logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) were sent",
+    logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) "
+           "were sent",
            responsesize-count, responsesize);
-    if(ptr)
-      free(ptr);
-    if(cmd)
-      free(cmd);
+    free(ptr);
+    free(cmd);
     return -1;
   }
 
   logmsg("Response sent (%zu bytes) and written to %s",
          responsesize, responsedump);
+  free(ptr);
 
-  if(ptr)
-    free(ptr);
-
-  if(cmdsize > 0 ) {
+  if(cmdsize > 0) {
     char command[32];
     int quarters;
     int num;
@@ -1285,9 +1291,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
         ptr = NULL;
     } while(ptr && *ptr);
   }
-  if(cmd)
-    free(cmd);
-
+  free(cmd);
   req->open = use_gopher?FALSE:persistant;
 
   prevtestno = req->testno;
@@ -1334,8 +1338,6 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
     if(0 != setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY,
                        (void *)&flag, sizeof(flag)))
       logmsg("====> TCP_NODELAY for server conection failed");
-    else
-      logmsg("TCP_NODELAY set for server conection");
   }
 #endif
 
@@ -1429,6 +1431,7 @@ static void http_connect(curl_socket_t *infdp,
   int max_tunnel_idx; /* CTRL or DATA */
   int loop;
   int i;
+  int timeout_count=0;
 
   /* primary tunnel client endpoint already connected */
   clientfd[CTRL] = *infdp;
@@ -1457,7 +1460,7 @@ static void http_connect(curl_socket_t *infdp,
 
     fd_set input;
     fd_set output;
-    struct timeval timeout = {0, 250000L}; /* 250 ms */
+    struct timeval timeout = {1, 0}; /* 1000 ms */
     ssize_t rc;
     curl_socket_t maxfd = (curl_socket_t)-1;
 
@@ -1518,6 +1521,7 @@ static void http_connect(curl_socket_t *infdp,
     if(rc > 0) {
       /* socket action */
       bool tcp_fin_wr;
+      timeout_count=0;
 
       if(got_exit_signal)
         break;
@@ -1543,8 +1547,6 @@ static void http_connect(curl_socket_t *infdp,
             if(0 != setsockopt(datafd, IPPROTO_TCP, TCP_NODELAY,
                                (void *)&flag, sizeof(flag)))
               logmsg("====> TCP_NODELAY for client DATA conection failed");
-            else
-              logmsg("TCP_NODELAY set for client DATA conection");
           }
 #endif
           req2.pipelining = FALSE;
@@ -1568,7 +1570,8 @@ static void http_connect(curl_socket_t *infdp,
                 /* connect to the server */
                 serverfd[DATA] = connect_to(ipaddr, req2.connect_port);
                 if(serverfd[DATA] != CURL_SOCKET_BAD) {
-                  /* secondary tunnel established, now we have two connections */
+                  /* secondary tunnel established, now we have two
+                     connections */
                   poll_client_rd[DATA] = TRUE;
                   poll_client_wr[DATA] = TRUE;
                   poll_server_rd[DATA] = TRUE;
@@ -1761,7 +1764,13 @@ static void http_connect(curl_socket_t *infdp,
         break;
 
     } /* (rc > 0) */
-
+    else {
+      timeout_count++;
+      if(timeout_count > 5) {
+        logmsg("CONNECT proxy timeout after %d idle seconds!", timeout_count);
+        break;
+      }
+    }
   }
 
 http_connect_cleanup:
@@ -1867,8 +1876,6 @@ static curl_socket_t accept_connection(curl_socket_t sock)
     if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
                        (void *)&flag, sizeof(flag)))
       logmsg("====> TCP_NODELAY failed");
-    else
-      logmsg("TCP_NODELAY set");
   }
 #endif
 
@@ -1886,7 +1893,7 @@ static int service_connection(curl_socket_t msgsock, struct httprequest *req,
 
   while(!req->done_processing) {
     int rc = get_request(msgsock, req);
-    if (rc <= 0) {
+    if(rc <= 0) {
       /* Nothing further to read now (possibly because the socket was closed */
       return rc;
     }
@@ -2165,7 +2172,7 @@ int main(int argc, char *argv[])
       /* socket server is not alive, now check if it was actually a socket.
        * Systems which have Unix sockets will also have lstat */
       rc = lstat(unix_socket, &statbuf);
-      if (0 != rc) {
+      if(0 != rc) {
         logmsg("Error binding socket, failed to stat %s: (%d) %s",
                unix_socket, errno, strerror(errno));
         goto sws_cleanup;
@@ -2235,11 +2242,11 @@ int main(int argc, char *argv[])
     curl_socket_t maxfd = (curl_socket_t)-1;
 
     /* Clear out closed sockets */
-    for (socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) {
-      if (CURL_SOCKET_BAD == all_sockets[socket_idx]) {
-        chardst = (char *) (all_sockets + socket_idx);
-        charsrc = (char *) (all_sockets + socket_idx + 1);
-        charend = (char *) (all_sockets + num_sockets);
+    for(socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) {
+      if(CURL_SOCKET_BAD == all_sockets[socket_idx]) {
+        char *dst = (char *) (all_sockets + socket_idx);
+        char *src = (char *) (all_sockets + socket_idx + 1);
+        char *end = (char *) (all_sockets + num_sockets);
         memmove(dst, src, end - src);
         num_sockets -= 1;
       }
@@ -2252,7 +2259,7 @@ int main(int argc, char *argv[])
     FD_ZERO(&input);
     FD_ZERO(&output);
 
-    for (socket_idx = 0; socket_idx < num_sockets; ++socket_idx) {
+    for(socket_idx = 0; socket_idx < num_sockets; ++socket_idx) {
       /* Listen on all sockets */
       FD_SET(all_sockets[socket_idx], &input);
       if(all_sockets[socket_idx] > maxfd)
@@ -2263,7 +2270,7 @@ int main(int argc, char *argv[])
       goto sws_cleanup;
 
     rc = select((int)maxfd + 1, &input, &output, NULL, &timeout);
-    if (rc < 0) {
+    if(rc < 0) {
       error = SOCKERRNO;
       logmsg("select() failed with error: (%d) %s",
              error, strerror(error));
@@ -2273,26 +2280,26 @@ int main(int argc, char *argv[])
     if(got_exit_signal)
       goto sws_cleanup;
 
-    if (rc == 0) {
+    if(rc == 0) {
       /* Timed out - try again*/
       continue;
     }
 
     /* Check if the listening socket is ready to accept */
-    if (FD_ISSET(all_sockets[0], &input)) {
+    if(FD_ISSET(all_sockets[0], &input)) {
       /* Service all queued connections */
       curl_socket_t msgsock;
       do {
         msgsock = accept_connection(sock);
         logmsg("accept_connection %d returned %d", sock, msgsock);
-        if (CURL_SOCKET_BAD == msgsock)
+        if(CURL_SOCKET_BAD == msgsock)
           goto sws_cleanup;
-      } while (msgsock > 0);
+      } while(msgsock > 0);
     }
 
     /* Service all connections that are ready */
-    for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx) {
-      if (FD_ISSET(all_sockets[socket_idx], &input)) {
+    for(socket_idx = 1; socket_idx < num_sockets; ++socket_idx) {
+      if(FD_ISSET(all_sockets[socket_idx], &input)) {
         if(got_exit_signal)
           goto sws_cleanup;
 
@@ -2303,7 +2310,7 @@ int main(int argc, char *argv[])
           if(got_exit_signal)
             goto sws_cleanup;
 
-          if (rc < 0) {
+          if(rc < 0) {
             logmsg("====> Client disconnect %d", req.connmon);
 
             if(req.connmon) {
@@ -2327,14 +2334,14 @@ int main(int argc, char *argv[])
             if(!serverlogslocked)
               clear_advisor_read_lock(SERVERLOGS_LOCK);
 
-            if (req.testno == DOCNUMBER_QUIT)
+            if(req.testno == DOCNUMBER_QUIT)
               goto sws_cleanup;
           }
 
           /* Reset the request, unless we're still in the middle of reading */
-          if (rc != 0)
+          if(rc != 0)
             init_httprequest(&req);
-        } while (rc > 0);
+        } while(rc > 0);
       }
     }
 
@@ -2344,7 +2351,7 @@ int main(int argc, char *argv[])
 
 sws_cleanup:
 
-  for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx)
+  for(socket_idx = 1; socket_idx < num_sockets; ++socket_idx)
     if((all_sockets[socket_idx] != sock) &&
      (all_sockets[socket_idx] != CURL_SOCKET_BAD))
       sclose(all_sockets[socket_idx]);