~ubuntu-branches/ubuntu/maverick/curl/maverick

« back to all changes in this revision

Viewing changes to tests/server/sws.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt
  • Date: 2008-06-18 15:21:57 UTC
  • mto: (3.1.1 lenny) (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 28.
  • Revision ID: james.westby@ubuntu.com-20080618152157-j8b12047aqcl6kii
Tags: upstream-7.18.2
ImportĀ upstreamĀ versionĀ 7.18.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
10
10
 * This software is licensed as described in the file COPYING, which
11
11
 * you should have received as part of this distribution. The terms
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.110 2008-01-25 05:08:53 yangtse Exp $
 
21
 * $Id: sws.c,v 1.120 2008-04-23 23:55:34 yangtse Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
/* sws.c: simple (silly?) web server
29
29
 */
30
30
#include "setup.h" /* portability help from the lib directory */
31
31
 
32
 
#include <stdio.h>
33
 
#include <stdlib.h>
34
 
#include <string.h>
35
 
#include <stdarg.h>
 
32
#ifdef HAVE_SIGNAL_H
36
33
#include <signal.h>
37
 
#include <time.h>
38
 
#include <sys/time.h>
39
 
#include <sys/types.h>
40
 
#include <ctype.h>
41
 
 
 
34
#endif
42
35
#ifdef HAVE_UNISTD_H
43
36
#include <unistd.h>
44
37
#endif
83
76
 
84
77
long prevtestno=-1; /* previous test number we served */
85
78
long prevpartno=-1; /* previous part number we served */
86
 
bool prevbounce;    /* instructs the server to increase the part number for
87
 
                       a test in case the identical testno+partno request
88
 
                       shows up again */
 
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 */
89
82
 
90
83
#define RCMD_NORMALREQ 0 /* default request, use the tests file normally */
91
84
#define RCMD_IDLE      1 /* told to sit idle */
97
90
  int offset;     /* size of the incoming request */
98
91
  long testno;     /* test number found in the request */
99
92
  long partno;     /* part number found in the request */
100
 
  int open;       /* keep connection open info, as found in the request */
 
93
  bool open;      /* keep connection open info, as found in the request */
101
94
  bool auth_req;  /* authentication required, don't wait for body unless
102
95
                     there's an Authorization header */
103
96
  bool auth;      /* Authorization header present in the incoming request */
132
125
#define MAXDOCNAMELEN_TXT "139999"
133
126
 
134
127
#define REQUEST_KEYWORD_SIZE 256
 
128
#define REQUEST_KEYWORD_SIZE_TXT "255"
135
129
 
136
130
#define CMD_AUTH_REQUIRED "auth_required"
137
131
 
196
190
int ProcessRequest(struct httprequest *req)
197
191
{
198
192
  char *line=&req->reqbuf[req->checkindex];
199
 
  char chunked=FALSE;
 
193
  bool chunked = FALSE;
200
194
  static char request[REQUEST_KEYWORD_SIZE];
201
195
  static char doc[MAXDOCNAMELEN];
202
196
  char logbuf[256];
210
204
  /* try to figure out the request characteristics as soon as possible, but
211
205
     only once! */
212
206
  if((req->testno == DOCNUMBER_NOTHING) &&
213
 
     sscanf(line, "%" REQBUFSIZ_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
 
207
     sscanf(line,
 
208
            "%" REQUEST_KEYWORD_SIZE_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
214
209
            request,
215
210
            doc,
216
211
            &prot_major,
475
470
/* store the entire request in a file */
476
471
void storerequest(char *reqbuf, ssize_t totalsize)
477
472
{
 
473
  int res;
478
474
  int error;
479
475
  ssize_t written;
480
476
  ssize_t writeleft;
509
505
      writeleft -= written;
510
506
  } while ((writeleft > 0) && ((error = ERRNO) == EINTR));
511
507
 
512
 
  fclose(dump);  /* close it ASAP */
513
 
 
514
508
  if (writeleft > 0) {
515
509
    logmsg("Error writing file %s error: %d %s",
516
510
           REQUEST_DUMP, error, strerror(error));
517
511
    logmsg("Wrote only (%d bytes) of (%d bytes) request input to %s",
518
512
           totalsize-writeleft, totalsize, REQUEST_DUMP);
519
513
  }
520
 
  else {
 
514
 
 
515
  do {
 
516
    res = fclose(dump);
 
517
  } while(res && ((error = ERRNO) == EINTR));
 
518
  if(res)
 
519
    logmsg("Error closing file %s error: %d %s",
 
520
           REQUEST_DUMP, error, strerror(error));
 
521
 
 
522
  if(!writeleft)
521
523
    logmsg("Wrote request (%d bytes) input to " REQUEST_DUMP,
522
524
           totalsize);
523
 
  }
524
525
}
525
526
 
526
527
/* return 0 on success, non-zero on failure */
527
528
static int get_request(curl_socket_t sock, struct httprequest *req)
528
529
{
529
 
  int fail= FALSE;
 
530
  int fail = 0;
530
531
  char *reqbuf = req->reqbuf;
531
 
 
532
 
  char pipereq[REQBUFSIZ];
533
 
  int pipereq_length;
 
532
  ssize_t got = 0;
 
533
 
 
534
  char *pipereq;
 
535
  int pipereq_length = 0;
 
536
 
534
537
  if(req->pipelining) {
 
538
    pipereq = reqbuf + req->checkindex;
535
539
    pipereq_length = req->offset - req->checkindex;
536
 
    memcpy(pipereq, reqbuf + req->checkindex, pipereq_length);
537
540
  }
538
 
  else
539
 
    pipereq_length = 0;
540
541
 
541
542
  /*** Init the httpreqest structure properly for the upcoming request ***/
542
 
  memset(req, 0, sizeof(struct httprequest));
543
543
 
544
 
  /* here's what should not be 0 from the start */
545
 
  req->testno = DOCNUMBER_NOTHING; /* safe default */
546
 
  req->open = TRUE; /* connection should remain open and wait for more
547
 
                       commands */
 
544
  req->checkindex = 0;
 
545
  req->offset = 0;
 
546
  req->testno = DOCNUMBER_NOTHING;
 
547
  req->partno = 0;
 
548
  req->open = TRUE;
 
549
  req->auth_req = FALSE;
 
550
  req->auth = FALSE;
 
551
  req->cl = 0;
 
552
  req->digest = FALSE;
 
553
  req->ntlm = FALSE;
548
554
  req->pipe = 0;
 
555
  req->rcmd = RCMD_NORMALREQ;
 
556
  req->prot_version = 0;
 
557
  req->pipelining = FALSE;
549
558
 
550
559
  /*** end of httprequest init ***/
551
560
 
552
 
  while (req->offset < REQBUFSIZ) {
553
 
    ssize_t got;
 
561
  while (req->offset < REQBUFSIZ-1) {
554
562
    if(pipereq_length) {
555
 
      memcpy(reqbuf, pipereq, pipereq_length);
 
563
      memmove(reqbuf, pipereq, pipereq_length); 
556
564
      got = pipereq_length;
557
565
      pipereq_length = 0;
558
566
    }
559
567
    else
560
 
      got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset);
 
568
      got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset);
561
569
    if (got <= 0) {
562
570
      if (got < 0) {
563
571
        logmsg("recv() returned error: %d", SOCKERRNO);
564
572
        return DOCNUMBER_INTERNAL;
565
573
      }
566
574
      logmsg("Connection closed by client");
567
 
      reqbuf[req->offset]=0;
 
575
      reqbuf[req->offset] = '\0';
568
576
 
569
577
      /* dump the request receivied so far to the external file */
570
578
      storerequest(reqbuf, req->offset);
574
582
    logmsg("Read %d bytes", got);
575
583
 
576
584
    req->offset += got;
577
 
 
578
 
    reqbuf[req->offset] = 0;
 
585
    reqbuf[req->offset] = '\0';
579
586
 
580
587
    if(ProcessRequest(req)) {
581
588
      if(req->pipe--) {
586
593
    }
587
594
  }
588
595
 
589
 
  if (req->offset >= REQBUFSIZ) {
 
596
  if((req->offset == REQBUFSIZ-1) && (got > 0)) {
 
597
    logmsg("Request would overflow buffer, closing connection");
 
598
    /* dump request received so far to external file anyway */
 
599
    reqbuf[REQBUFSIZ-1] = '\0';
 
600
    fail = 1;
 
601
  }
 
602
  else if(req->offset > REQBUFSIZ-1) {
590
603
    logmsg("Request buffer overflow, closing connection");
591
 
    reqbuf[REQBUFSIZ-1]=0;
592
 
    fail = TRUE;
593
 
    /* dump the request to an external file anyway */
 
604
    /* dump request received so far to external file anyway */
 
605
    reqbuf[REQBUFSIZ-1] = '\0';
 
606
    fail = 1;
594
607
  }
595
608
  else
596
 
    reqbuf[req->offset]=0;
 
609
    reqbuf[req->offset] = '\0';
597
610
 
598
611
  /* dump the request to an external file */
599
612
  storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
600
613
 
601
 
  return fail; /* success */
 
614
  return fail; /* return 0 on success */
602
615
}
603
616
 
604
617
/* returns -1 on failure */
607
620
  ssize_t written;
608
621
  size_t count;
609
622
  const char *buffer;
610
 
  char *ptr;
 
623
  char *ptr=NULL;
611
624
  FILE *stream;
612
625
  char *cmd=NULL;
613
626
  size_t cmdsize=0;
614
627
  FILE *dump;
615
 
  int persistant = TRUE;
 
628
  bool persistant = TRUE;
 
629
  bool sendfailure = FALSE;
616
630
  size_t responsesize;
617
631
  int error;
 
632
  int res;
618
633
 
619
634
  static char weare[256];
620
635
 
656
671
    case DOCNUMBER_WERULEZ:
657
672
      /* we got a "friends?" question, reply back that we sure are */
658
673
      logmsg("Identifying ourselves as friends");
659
 
      sprintf(msgbuf, "WE ROOLZ: %d\r\n", (int)getpid());
 
674
      sprintf(msgbuf, "WE ROOLZ: %ld\r\n", (long)getpid());
660
675
      msglen = strlen(msgbuf);
661
676
      sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s",
662
677
              msglen, msgbuf);
754
769
      num = 200;
755
770
    written = swrite(sock, buffer, num);
756
771
    if (written < 0) {
757
 
      fclose(dump);
758
 
      logmsg("Sending response failed and we bailed out!");
759
 
      return -1;
 
772
      sendfailure = TRUE;
 
773
      break;
760
774
    }
761
775
    else {
762
776
      logmsg("Sent off %d bytes", written);
768
782
    buffer += written;
769
783
  } while(count>0);
770
784
 
771
 
  fclose(dump);
 
785
  do {
 
786
    res = fclose(dump);
 
787
  } while(res && ((error = ERRNO) == EINTR));
 
788
  if(res)
 
789
    logmsg("Error closing file %s error: %d %s",
 
790
           RESPONSE_DUMP, error, strerror(error));
 
791
 
 
792
  if(sendfailure) {
 
793
    logmsg("Sending response failed. Only (%d bytes) of (%d bytes) were sent",
 
794
           responsesize-count, responsesize);
 
795
    if(ptr)
 
796
      free(ptr);
 
797
    if(cmd)
 
798
      free(cmd);
 
799
    return -1;
 
800
  }
772
801
 
773
802
  logmsg("Response sent (%d bytes) and written to " RESPONSE_DUMP,
774
803
         responsesize);
807
836
  return 0;
808
837
}
809
838
 
810
 
char use_ipv6=FALSE;
 
839
bool use_ipv6=FALSE;
811
840
 
812
841
int main(int argc, char *argv[])
813
842
{
818
847
  curl_socket_t sock, msgsock;
819
848
  int flag;
820
849
  unsigned short port = DEFAULT_PORT;
821
 
  FILE *pidfile;
822
850
  char *pidname= (char *)".http.pid";
823
851
  struct httprequest req;
824
852
  int rc;
825
 
  int error;
826
853
  int arg=1;
827
854
#ifdef CURL_SWS_FORK_ENABLED
828
855
  bool use_fork = FALSE;
932
959
    return 1;
933
960
  }
934
961
 
935
 
  pidfile = fopen(pidname, "w");
936
 
  if(pidfile) {
937
 
    fprintf(pidfile, "%d\n", (int)getpid());
938
 
    fclose(pidfile);
939
 
  }
940
 
  else {
941
 
    error = ERRNO;
942
 
    logmsg("fopen() failed with error: %d %s", error, strerror(error));
943
 
    logmsg("Error opening file: %s", pidname);
944
 
    logmsg("Couldn't write pid file");
 
962
  if(!write_pidfile(pidname)) {
945
963
    sclose(sock);
946
964
    return 1;
947
965
  }
970
988
      break;
971
989
    }
972
990
 
 
991
    set_advisor_read_lock(SERVERLOGS_LOCK);
 
992
 
973
993
#ifdef CURL_SWS_FORK_ENABLED
974
994
    if(use_fork) {
975
995
      /* The fork enabled version just forks off the child and don't care
1001
1021
    }
1002
1022
#endif
1003
1023
 
1004
 
  /* full initialization for new request after connection */
1005
 
  memset(&req, 0, sizeof(req));
1006
 
  req.testno = DOCNUMBER_NOTHING;
1007
 
  req.open = TRUE;
1008
 
  req.auth_req = FALSE;
1009
 
  req.auth = FALSE;
1010
 
  req.digest = FALSE;
1011
 
  req.ntlm = FALSE;
1012
 
  req.pipelining = FALSE;
1013
 
 
1014
 
  do {
 
1024
    /* initialization of httprequest struct is done in get_request(), but due
 
1025
       to pipelining treatment the pipelining struct field must be initialized
 
1026
       previously to FALSE every time a new connection arrives. */
 
1027
 
 
1028
    req.pipelining = FALSE;
 
1029
 
 
1030
    do {
1015
1031
      if(get_request(msgsock, &req))
1016
1032
        /* non-zero means error, break out of loop */
1017
1033
        break;
1023
1039
          req.partno++;
1024
1040
          logmsg("BOUNCE part number to %ld", req.partno);
1025
1041
        }
 
1042
        else {
 
1043
          prevbounce = FALSE;
 
1044
          prevtestno = -1;
 
1045
          prevpartno = -1;
 
1046
        }
1026
1047
      }
1027
1048
 
1028
1049
      send_doc(msgsock, &req);
1044
1065
    logmsg("====> Client disconnect");
1045
1066
    sclose(msgsock);
1046
1067
 
 
1068
    clear_advisor_read_lock(SERVERLOGS_LOCK);
 
1069
 
1047
1070
    if (req.testno == DOCNUMBER_QUIT)
1048
1071
      break;
1049
1072
#ifdef CURL_SWS_FORK_ENABLED
1053
1076
 
1054
1077
  sclose(sock);
1055
1078
 
 
1079
  clear_advisor_read_lock(SERVERLOGS_LOCK);
 
1080
 
1056
1081
  return 0;
1057
1082
}
1058
1083