sws: added basic gopher support
authorDaniel Stenberg <daniel@haxx.se>
Tue, 24 Aug 2010 22:45:52 +0000 (00:45 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 25 Aug 2010 12:21:25 +0000 (14:21 +0200)
tests/server/sws.c

index 44a84a9..8a93b3b 100644 (file)
@@ -75,6 +75,7 @@
 #ifdef ENABLE_IPV6
 static bool use_ipv6 = FALSE;
 #endif
+static bool use_gopher = FALSE;
 static const char *ipv_inuse = "IPv4";
 static int serverlogslocked = 0;
 
@@ -159,6 +160,7 @@ enum {
   DOCNUMBER_404     = -1
 };
 
+const char *end_of_headers = END_OF_HEADERS;
 
 /* sent as reply to a QUIT */
 static const char *docquit =
@@ -307,13 +309,22 @@ static int ProcessRequest(struct httprequest *req)
   int prot_major, prot_minor;
   char *end;
   int error;
-  end = strstr(line, END_OF_HEADERS);
+  end = strstr(line, end_of_headers);
 
   logmsg("ProcessRequest() called");
 
   /* try to figure out the request characteristics as soon as possible, but
      only once! */
-  if((req->testno == DOCNUMBER_NOTHING) &&
+
+  if(use_gopher &&
+     (req->testno == DOCNUMBER_NOTHING) &&
+     !strncmp("/verifiedserver", line, 15)) {
+    logmsg("Are-we-friendly question received");
+    req->testno = DOCNUMBER_WERULEZ;
+    return 1; /* done */
+  }
+
+  else if((req->testno == DOCNUMBER_NOTHING) &&
      sscanf(line,
             "%" REQUEST_KEYWORD_SIZE_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
             request,
@@ -471,10 +482,40 @@ static int ProcessRequest(struct httprequest *req)
   }
   logmsg("ProcessRequest found a complete request");
 
+  if(use_gopher) {
+    /* when using gopher we cannot check the request until the entire
+       thing has been received */
+    char *ptr;
+
+    /* find the last slash in the line */
+    ptr = strrchr(line, '/');
+
+    if(ptr) {
+      ptr++; /* skip the slash */
+
+      /* skip all non-numericals following the slash */
+      while(*ptr && !ISDIGIT(*ptr))
+        ptr++;
+
+      req->testno = strtol(ptr, &ptr, 10);
+
+      if(req->testno > 10000) {
+        req->partno = req->testno % 10000;
+        req->testno /= 10000;
+      }
+      else
+        req->partno = 0;
+
+      sprintf(logbuf, "Requested GOPHER test number %ld part %ld",
+              req->testno, req->partno);
+      logmsg("%s", logbuf);
+    }
+  }
+
   if(req->pipe)
     /* we do have a full set, advance the checkindex to after the end of the
        headers, for the pipelining case mostly */
-    req->checkindex += (end - line) + strlen(END_OF_HEADERS);
+    req->checkindex += (end - line) + strlen(end_of_headers);
 
   /* **** Persistence ****
    *
@@ -582,12 +623,12 @@ static int ProcessRequest(struct httprequest *req)
      req->open &&
      req->prot_version >= 11 &&
      end &&
-     req->reqbuf + req->offset > end + strlen(END_OF_HEADERS) &&
+     req->reqbuf + req->offset > end + strlen(end_of_headers) &&
      (!strncmp(req->reqbuf, "GET", strlen("GET")) ||
       !strncmp(req->reqbuf, "HEAD", strlen("HEAD")))) {
     /* If we have a persistent connection, HTTP version >= 1.1
        and GET/HEAD request, enable pipelining. */
-    req->checkindex = (end - req->reqbuf) + strlen(END_OF_HEADERS);
+    req->checkindex = (end - req->reqbuf) + strlen(end_of_headers);
     req->pipelining = TRUE;
   }
 
@@ -596,10 +637,10 @@ static int ProcessRequest(struct httprequest *req)
       return 1; /* done */
     /* scan for more header ends within this chunk */
     line = &req->reqbuf[req->checkindex];
-    end = strstr(line, END_OF_HEADERS);
+    end = strstr(line, end_of_headers);
     if(!end)
       break;
-    req->checkindex += (end - line) + strlen(END_OF_HEADERS);
+    req->checkindex += (end - line) + strlen(end_of_headers);
     req->pipe--;
   }
 
@@ -611,7 +652,7 @@ static int ProcessRequest(struct httprequest *req)
     return 1; /* done */
 
   if(req->cl > 0) {
-    if(req->cl <= req->offset - (end - req->reqbuf) - strlen(END_OF_HEADERS))
+    if(req->cl <= req->offset - (end - req->reqbuf) - strlen(end_of_headers))
       return 1; /* done */
     else
       return 0; /* not complete yet */
@@ -842,8 +883,11 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
       logmsg("Identifying ourselves as friends");
       sprintf(msgbuf, "WE ROOLZ: %ld\r\n", (long)getpid());
       msglen = strlen(msgbuf);
-      sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
-              msglen, msgbuf);
+      if(use_gopher)
+        sprintf(weare, "%s", msgbuf);
+      else
+        sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
+                msglen, msgbuf);
       buffer = weare;
       break;
     case DOCNUMBER_INTERNAL:
@@ -1050,7 +1094,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
   if(cmd)
     free(cmd);
 
-  req->open = persistant;
+  req->open = use_gopher?FALSE:persistant;
 
   prevtestno = req->testno;
   prevpartno = req->partno;
@@ -1106,6 +1150,11 @@ int main(int argc, char *argv[])
       if(argc>arg)
         serverlogfile = argv[arg++];
     }
+    else if(!strcmp("--gopher", argv[arg])) {
+      arg++;
+      use_gopher = TRUE;
+      end_of_headers = "\r\n"; /* gopher style is much simpler */
+    }
     else if(!strcmp("--ipv4", argv[arg])) {
 #ifdef ENABLE_IPV6
       ipv_inuse = "IPv4";
@@ -1157,6 +1206,7 @@ int main(int argc, char *argv[])
            " --ipv6\n"
            " --port [port]\n"
            " --srcdir [path]\n"
+           " --gopher\n"
            " --fork");
       return 0;
     }
@@ -1221,7 +1271,8 @@ int main(int argc, char *argv[])
     goto sws_cleanup;
   }
 
-  logmsg("Running %s version on port %d", ipv_inuse, (int)port);
+  logmsg("Running %s %s version on port %d",
+         use_gopher?"GOPHER":"HTTP", ipv_inuse, (int)port);
 
   /* start accepting connections */
   rc = listen(sock, 5);