]> code.citadel.org Git - citadel.git/blobdiff - webcit/context_loop.c
* converted to autoconf and began port to Digital UNIX
[citadel.git] / webcit / context_loop.c
index bcf5c77117644e37b6c844a7b42b33ee5a9681c9..a82c583e9dbb59b33a21fd2bbc6a67ebc9a70c13 100644 (file)
@@ -5,8 +5,11 @@
  * up HTTP requests with the session they belong to, using HTTP cookies to
  * keep track of things.  If the HTTP request doesn't belong to any currently
  * active session, a new session is spawned.
+ *
+ * $Id$
  */
 
+#include <ctype.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -24,6 +27,7 @@
 #include <stdarg.h>
 #include <pthread.h>
 #include "webcit.h"
+#include "webserver.h"
 
 /*
  * We keep one of these around for each active session
@@ -38,6 +42,9 @@ struct wc_session {
 
 struct wc_session *SessionList = NULL;
 
+/* Only one thread may manipulate SessionList at a time... */
+pthread_mutex_t MasterCritter;
+
 int GenerateSessionID() {
        return getpid();
        }
@@ -77,24 +84,26 @@ void req_gets(int sock, char *buf, char *hold) {
                }
        }
 
+extern const char *defaulthost;
+extern const char *defaultport;
 
 /*
  * This loop gets called once for every HTTP connection made to WebCit.
  */
-void *context_loop(int *socknumptr) {
+void *context_loop(int sock) {
        char req[256][256];
        char buf[256], hold[256];
        int num_lines = 0;
        int a;
        int f;
-       int sock;
        int desired_session = 0;
        char str_session[256];
        struct wc_session *sptr;
        struct wc_session *TheSession;
        int ContentLength;
+       int CloseSession = 0;
 
-       sock = *socknumptr;
+       printf("Reading request from socket %d\n", sock);
 
        /*
         * Find out what it is that the web browser is asking for
@@ -116,11 +125,13 @@ void *context_loop(int *socknumptr) {
         */
        TheSession = NULL;
        if (desired_session != 0) {
+               pthread_mutex_lock(&MasterCritter);
                for (sptr=SessionList; sptr!=NULL; sptr=sptr->next) {
                        if (sptr->session_id == desired_session) {
                                TheSession = sptr;
                                }
                        }
+               pthread_mutex_unlock(&MasterCritter);
                }
 
        /*
@@ -128,12 +139,13 @@ void *context_loop(int *socknumptr) {
         */
        if (TheSession == NULL) {
                printf("Creating a new session\n");
+               pthread_mutex_lock(&MasterCritter);
                TheSession = (struct wc_session *)
                        malloc(sizeof(struct wc_session));
                TheSession->session_id = GenerateSessionID();
-               pthread_mutex_init(&TheSession->critter, NULL);
                pipe(TheSession->inpipe);
                pipe(TheSession->outpipe);
+               pthread_mutex_init(&TheSession->critter, NULL);
                TheSession->next = SessionList;
                SessionList = TheSession;
                sprintf(str_session, "%d", TheSession->session_id);
@@ -142,7 +154,8 @@ void *context_loop(int *socknumptr) {
                if (f==0) {
                        dup2(TheSession->inpipe[0], 0);
                        dup2(TheSession->outpipe[1], 1);
-                       execlp("./webcit", "webcit", str_session, NULL);
+                       execlp("./webcit", "webcit", str_session, defaulthost,
+                              defaultport, NULL);
                        printf("HTTP/1.0 404 WebCit Failure\n\n");
                        printf("Server: %s\n", SERVER);
                        printf("Content-type: text/html\n");
@@ -152,24 +165,36 @@ void *context_loop(int *socknumptr) {
                        printf("<BODY>execlp() failed</BODY></HTML>\n");
                        exit(0);
                        }
+               pthread_mutex_unlock(&MasterCritter);
                }
 
-       /* 
-        * Send the request to the appropriate session
+       /*
+        * Grab a lock on the session, so other threads don't try to access
+        * the pipes at the same time.
         */
+       printf("Locking session %d...\n", TheSession->session_id);
        pthread_mutex_lock(&TheSession->critter);
+       printf("   ...got lock\n");
+
+       /* 
+        * Send the request to the appropriate session...
+        */
+       printf("   Writing %d lines of command\n", num_lines);
+       printf("%s\n", &req[0][0]);
        for (a=0; a<num_lines; ++a) {
                write(TheSession->inpipe[1], &req[a][0], strlen(&req[a][0]));
                write(TheSession->inpipe[1], "\n", 1);
                }
+       printf("   Writing %d bytes of content\n", ContentLength);
        while (ContentLength--) {
                read(sock, buf, 1);
                write(TheSession->inpipe[1], buf, 1);
                }
 
        /*
-        * ...and get the response (FIX for non-text)
+        * ...and get the response.
         */
+       printf("   Reading response\n");
        ContentLength = 0;
        do {
                gets0(TheSession->outpipe[0], buf);
@@ -177,20 +202,61 @@ void *context_loop(int *socknumptr) {
                write(sock, "\n", 1);
                if (!strncasecmp(buf, "Content-length: ", 16))
                        ContentLength = atoi(&buf[16]);
+               if (!strcasecmp(buf, "X-WebCit-Session: close")) {
+                       CloseSession = 1;
+                       }
                } while (strlen(buf) > 0);
 
+       printf("   Reading %d bytes of content\n", ContentLength);
        while(ContentLength--) {
                read(TheSession->outpipe[0], buf, 1);
                write(sock, buf, 1);
                }
 
-       pthread_mutex_unlock(&TheSession->critter);
-
        /*
         * Now our HTTP connection is done.  It would be relatively easy
         * to support HTTP/1.1 "persistent" connections by looping back to
-        * the top of this function.  For now, we'll just exit.
+        * the top of this function.  For now, we'll just close.
         */
+       printf("   Closing socket\n");
        close(sock);
-       pthread_exit(NULL);
+
+       /*
+        * Let go of the lock
+        */
+       printf("Unlocking.\n");
+       pthread_mutex_unlock(&TheSession->critter);
+
+
+
+       /*
+        * If the last response included a "close session" directive,
+        * remove the context now.
+        */
+       if (CloseSession) {
+               printf("Removing session.\n");
+               pthread_mutex_lock(&MasterCritter);
+
+               if (SessionList==TheSession) {
+                       SessionList = SessionList->next;
+                       }
+               else {
+                       for (sptr=SessionList; sptr!=NULL; sptr=sptr->next) {
+                               if (sptr->next == TheSession) {
+                                       sptr->next = TheSession->next;
+                                       }
+                               }
+                       }
+       
+               free(TheSession);
+       
+               pthread_mutex_unlock(&MasterCritter);
+               }
+
+
+
+       /*
+        * The thread handling this HTTP connection is now finished.
+        */
+       return NULL;
        }