~ubuntu-branches/ubuntu/vivid/curl/vivid

« back to all changes in this revision

Viewing changes to tests/server/sws.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Schuldei
  • Date: 2009-04-02 23:35:45 UTC
  • mto: (1.2.1 upstream) (3.2.3 sid)
  • mto: This revision was merged to the branch mainline in revision 38.
  • Revision ID: james.westby@ubuntu.com-20090402233545-geixkwhe3izccjt7
Tags: upstream-7.19.4
ImportĀ upstreamĀ versionĀ 7.19.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: sws.c,v 1.120 2008-04-23 23:55:34 yangtse Exp $
 
21
 * $Id: sws.c,v 1.130 2008-11-25 23:23:47 danf Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
/* sws.c: simple (silly?) web server
71
71
#define CURL_SWS_FORK_ENABLED
72
72
#endif
73
73
 
 
74
#ifdef ENABLE_IPV6
 
75
static bool use_ipv6 = FALSE;
 
76
#endif
 
77
static const char *ipv_inuse = "IPv4";
 
78
 
74
79
#define REQBUFSIZ 150000
75
80
#define REQBUFSIZ_TXT "149999"
76
81
 
77
 
long prevtestno=-1; /* previous test number we served */
78
 
long prevpartno=-1; /* previous part number we served */
79
 
bool prevbounce=FALSE; /* instructs the server to increase the part number for
80
 
                          a test in case the identical testno+partno request
81
 
                          shows up again */
 
82
static long prevtestno=-1;    /* previous test number we served */
 
83
static long prevpartno=-1;    /* previous part number we served */
 
84
static bool prevbounce=FALSE; /* instructs the server to increase the part
 
85
                                 number for a test in case the identical
 
86
                                 testno+partno request shows up again */
82
87
 
83
88
#define RCMD_NORMALREQ 0 /* default request, use the tests file normally */
84
89
#define RCMD_IDLE      1 /* told to sit idle */
99
104
  bool ntlm;      /* Authorization ntlm header found */
100
105
  int pipe;       /* if non-zero, expect this many requests to do a "piped"
101
106
                     request/response */
 
107
  int skip;       /* if non-zero, the server is instructed to not read this
 
108
                     many bytes from a PUT/POST request. Ie the client sends N
 
109
                     bytes said in Content-Length, but the server only reads N
 
110
                     - skip bytes. */
102
111
  int rcmd;       /* doing a special command, see defines above */
103
112
  int prot_version; /* HTTP version * 10 */
104
113
  bool pipelining; /* true if request is pipelined */
105
114
};
106
115
 
107
 
int ProcessRequest(struct httprequest *req);
108
 
void storerequest(char *reqbuf, ssize_t totalsize);
 
116
static int ProcessRequest(struct httprequest *req);
 
117
static void storerequest(char *reqbuf, ssize_t totalsize);
109
118
 
110
119
#define DEFAULT_PORT 8999
111
120
 
187
196
}
188
197
#endif
189
198
 
190
 
int ProcessRequest(struct httprequest *req)
 
199
static int ProcessRequest(struct httprequest *req)
191
200
{
192
201
  char *line=&req->reqbuf[req->checkindex];
193
202
  bool chunked = FALSE;
269
278
        error = ERRNO;
270
279
        logmsg("fopen() failed with error: %d %s", error, strerror(error));
271
280
        logmsg("Error opening file: %s", filename);
272
 
        logmsg("Couldn't open test file %d", req->testno);
 
281
        logmsg("Couldn't open test file %ld", req->testno);
273
282
        req->open = FALSE; /* closes connection */
274
283
        return 1; /* done */
275
284
      }
303
312
            req->pipe = num-1; /* decrease by one since we don't count the
304
313
                                  first request in this number */
305
314
          }
 
315
          else if(1 == sscanf(cmd, "skip: %d", &num)) {
 
316
            logmsg("instructed to skip this number of bytes %d", num);
 
317
            req->skip = num;
 
318
          }
 
319
          else {
 
320
            logmsg("funny instruction found: %s", cmd);
 
321
          }
306
322
          free(cmd);
307
323
        }
308
324
      }
351
367
       headers, for the pipelining case mostly */
352
368
    req->checkindex += (end - line) + strlen(END_OF_HEADERS);
353
369
 
354
 
  /* **** Persistancy ****
 
370
  /* **** Persistence ****
355
371
   *
356
372
   * If the request is a HTTP/1.0 one, we close the connection unconditionally
357
373
   * when we're done.
363
379
   */
364
380
 
365
381
  do {
366
 
    if(!req->cl && curlx_strnequal("Content-Length:", line, 15)) {
 
382
    if((req->cl==0) && curlx_strnequal("Content-Length:", line, 15)) {
367
383
      /* If we don't ignore content-length, we read it and we read the whole
368
384
         request including the body before we return. If we've been told to
369
385
         ignore the content-length, we will return as soon as all headers
370
386
         have been received */
371
 
      req->cl = strtol(line+15, &line, 10);
 
387
      size_t cl = strtol(line+15, &line, 10);
 
388
      req->cl = cl - req->skip;
372
389
 
373
 
      logmsg("Found Content-Length: %d in the request", req->cl);
 
390
      logmsg("Found Content-Length: %zu in the request", cl);
 
391
      if(req->skip)
 
392
        logmsg("... but will abort after %zu bytes", req->cl);
374
393
      break;
375
394
    }
376
395
    else if(curlx_strnequal("Transfer-Encoding: chunked", line,
404
423
       Digest stuff to work in the test suite. */
405
424
    req->partno += 1000;
406
425
    req->digest = TRUE; /* header found */
407
 
    logmsg("Received Digest request, sending back data %d", req->partno);
 
426
    logmsg("Received Digest request, sending back data %ld", req->partno);
408
427
  }
409
428
  else if(!req->ntlm &&
410
429
          strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) {
411
430
    /* If the client is passing this type-3 NTLM header */
412
431
    req->partno += 1002;
413
432
    req->ntlm = TRUE; /* NTLM found */
414
 
    logmsg("Received NTLM type-3, sending back data %d", req->partno);
 
433
    logmsg("Received NTLM type-3, sending back data %ld", req->partno);
415
434
    if(req->cl) {
416
 
      logmsg("  Expecting %d POSTed bytes", req->cl);
 
435
      logmsg("  Expecting %zu POSTed bytes", req->cl);
417
436
    }
418
437
  }
419
438
  else if(!req->ntlm &&
421
440
    /* If the client is passing this type-1 NTLM header */
422
441
    req->partno += 1001;
423
442
    req->ntlm = TRUE; /* NTLM found */
424
 
    logmsg("Received NTLM type-1, sending back data %d", req->partno);
 
443
    logmsg("Received NTLM type-1, sending back data %ld", req->partno);
 
444
  }
 
445
  else if((req->partno >= 1000) && strstr(req->reqbuf, "Authorization: Basic")) {
 
446
    /* If the client is passing this Basic-header and the part number is already
 
447
       >=1000, we add 1 to the part number.  This allows simple Basic authentication
 
448
       negotiation to work in the test suite. */
 
449
    req->partno += 1;
 
450
    logmsg("Received Basic request, sending back data %ld", req->partno);
425
451
  }
426
452
  if(strstr(req->reqbuf, "Connection: close"))
427
453
    req->open = FALSE; /* close connection after this request */
457
483
  if(req->auth_req && !req->auth)
458
484
    return 1;
459
485
 
460
 
  if(req->cl) {
 
486
  if(req->cl > 0) {
461
487
    if(req->cl <= req->offset - (end - req->reqbuf) - strlen(END_OF_HEADERS))
462
488
      return 1; /* done */
463
489
    else
468
494
}
469
495
 
470
496
/* store the entire request in a file */
471
 
void storerequest(char *reqbuf, ssize_t totalsize)
 
497
static void storerequest(char *reqbuf, ssize_t totalsize)
472
498
{
473
499
  int res;
474
 
  int error;
 
500
  int error = 0;
475
501
  ssize_t written;
476
502
  ssize_t writeleft;
477
503
  FILE *dump;
482
508
  if (totalsize == 0)
483
509
    return;
484
510
  else if (totalsize < 0) {
485
 
    logmsg("Invalid size (%d bytes) for request input. Not written to %s",
 
511
    logmsg("Invalid size (%zd bytes) for request input. Not written to %s",
486
512
           totalsize, REQUEST_DUMP);
487
513
    return;
488
514
  }
508
534
  if (writeleft > 0) {
509
535
    logmsg("Error writing file %s error: %d %s",
510
536
           REQUEST_DUMP, error, strerror(error));
511
 
    logmsg("Wrote only (%d bytes) of (%d bytes) request input to %s",
 
537
    logmsg("Wrote only (%zd bytes) of (%zd bytes) request input to %s",
512
538
           totalsize-writeleft, totalsize, REQUEST_DUMP);
513
539
  }
514
540
 
520
546
           REQUEST_DUMP, error, strerror(error));
521
547
 
522
548
  if(!writeleft)
523
 
    logmsg("Wrote request (%d bytes) input to " REQUEST_DUMP,
 
549
    logmsg("Wrote request (%zd bytes) input to " REQUEST_DUMP,
524
550
           totalsize);
525
551
}
526
552
 
531
557
  char *reqbuf = req->reqbuf;
532
558
  ssize_t got = 0;
533
559
 
534
 
  char *pipereq;
 
560
  char *pipereq = NULL;
535
561
  int pipereq_length = 0;
536
562
 
537
563
  if(req->pipelining) {
539
565
    pipereq_length = req->offset - req->checkindex;
540
566
  }
541
567
 
542
 
  /*** Init the httpreqest structure properly for the upcoming request ***/
 
568
  /*** Init the httprequest structure properly for the upcoming request ***/
543
569
 
544
570
  req->checkindex = 0;
545
571
  req->offset = 0;
552
578
  req->digest = FALSE;
553
579
  req->ntlm = FALSE;
554
580
  req->pipe = 0;
 
581
  req->skip = 0;
555
582
  req->rcmd = RCMD_NORMALREQ;
556
583
  req->prot_version = 0;
557
584
  req->pipelining = FALSE;
560
587
 
561
588
  while (req->offset < REQBUFSIZ-1) {
562
589
    if(pipereq_length) {
563
 
      memmove(reqbuf, pipereq, pipereq_length); 
 
590
      memmove(reqbuf, pipereq, pipereq_length);
564
591
      got = pipereq_length;
565
592
      pipereq_length = 0;
566
593
    }
567
 
    else
568
 
      got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset);
 
594
    else {
 
595
      if(req->skip)
 
596
        /* we are instructed to not read the entire thing, so we make sure to only
 
597
           read what we're supposed to and NOT read the enire thing the client
 
598
           wants to send! */
 
599
        got = sread(sock, reqbuf + req->offset, req->cl);
 
600
      else
 
601
        got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset);
 
602
    }
569
603
    if (got <= 0) {
570
604
      if (got < 0) {
571
605
        logmsg("recv() returned error: %d", SOCKERRNO);
579
613
      return DOCNUMBER_INTERNAL;
580
614
    }
581
615
 
582
 
    logmsg("Read %d bytes", got);
 
616
    logmsg("Read %zd bytes", got);
583
617
 
584
618
    req->offset += got;
585
619
    reqbuf[req->offset] = '\0';
628
662
  bool persistant = TRUE;
629
663
  bool sendfailure = FALSE;
630
664
  size_t responsesize;
631
 
  int error;
 
665
  int error = 0;
632
666
  int res;
633
667
 
634
668
  static char weare[256];
635
669
 
636
670
  char partbuf[80]="data";
637
671
 
638
 
  logmsg("Send response number %d part %d", req->testno, req->partno);
 
672
  logmsg("Send response number %ld part %ld", req->testno, req->partno);
639
673
 
640
674
  switch(req->rcmd) {
641
675
  default:
673
707
      logmsg("Identifying ourselves as friends");
674
708
      sprintf(msgbuf, "WE ROOLZ: %ld\r\n", (long)getpid());
675
709
      msglen = strlen(msgbuf);
676
 
      sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s",
 
710
      sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
677
711
              msglen, msgbuf);
678
712
      buffer = weare;
679
713
      break;
773
807
      break;
774
808
    }
775
809
    else {
776
 
      logmsg("Sent off %d bytes", written);
 
810
      logmsg("Sent off %zd bytes", written);
777
811
    }
778
812
    /* write to file as well */
779
813
    fwrite(buffer, 1, written, dump);
790
824
           RESPONSE_DUMP, error, strerror(error));
791
825
 
792
826
  if(sendfailure) {
793
 
    logmsg("Sending response failed. Only (%d bytes) of (%d bytes) were sent",
 
827
    logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) were sent",
794
828
           responsesize-count, responsesize);
795
829
    if(ptr)
796
830
      free(ptr);
799
833
    return -1;
800
834
  }
801
835
 
802
 
  logmsg("Response sent (%d bytes) and written to " RESPONSE_DUMP,
 
836
  logmsg("Response sent (%zu bytes) and written to " RESPONSE_DUMP,
803
837
         responsesize);
804
838
 
805
839
  if(ptr)
836
870
  return 0;
837
871
}
838
872
 
839
 
bool use_ipv6=FALSE;
840
873
 
841
874
int main(int argc, char *argv[])
842
875
{
878
911
    }
879
912
    else if(!strcmp("--ipv6", argv[arg])) {
880
913
#ifdef ENABLE_IPV6
881
 
      use_ipv6=TRUE;
 
914
      ipv_inuse = "IPv6";
 
915
      use_ipv6 = TRUE;
882
916
#endif
883
917
      arg++;
884
918
    }
964
998
    return 1;
965
999
  }
966
1000
 
967
 
  logmsg("Running IPv%d version on port %d",
968
 
#ifdef ENABLE_IPV6
969
 
         (use_ipv6?6:4)
970
 
#else
971
 
         4
972
 
#endif
973
 
         , port );
 
1001
  logmsg("Running %s version on port %d", ipv_inuse, (int)port);
974
1002
 
975
1003
  /* start accepting connections */
976
1004
  rc = listen(sock, 5);
1049
1077
      send_doc(msgsock, &req);
1050
1078
 
1051
1079
      if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) {
1052
 
        logmsg("special request received, no persistancy");
 
1080
        logmsg("special request received, no persistency");
1053
1081
        break;
1054
1082
      }
1055
1083
      if(!req.open) {