mod_fastcgi for apache with BUFF support

Nigel Metheringham (Nigel.Metheringham@theplanet.net)
Mon, 24 Jun 1996 15:56:07 +0100

Message-Id: <m0uYD3g-0006Y3C@dingo.theplanet.co.uk>
To: Mark Brown <mbrown@openmarket.com>
From: Nigel Metheringham <Nigel.Metheringham@theplanet.net>
Subject: mod_fastcgi for apache with BUFF support
Date: Mon, 24 Jun 1996 15:56:07 +0100

This is a multipart MIME message.

--===_0_Mon_Jun_24_15:54:44_BST_1996
Content-Type: text/plain; charset=us-ascii

I wanted to get a version of apache with both SSL and fastcgi support 
going, but with the 1.0.5 paradigm thats hard - you need to stop 
fastcgi directly reading the fd and make it use SSL instead.

With the 1.1 versions you can cheat and put the SSL stuff into the 
BUFF structure which all the reads/writes go through, and everything 
works transparently..... everything that is other than fastcgi which 
breaks modularity and goes for that fd!

Here is a patch for mod_fastcgi.c which makes all the communication 
with the client occur through the buffered io stuff.  This means it 
works with an apache SSL server which I hacked up - however the SSL 
stuff is *not* available at present, although Ben has the patches.  
He intends to release something as soon as apache 1.1 is stable.

NB This only changes mod_fastcgi.c to use apache buffered I/O, it 
does not contain any encryption hooks or things that could upset your 
legal people :-)

The client I/O is now *not* select driven and so could block.  I 
don't think this is a real problem in practice, but go ahead and 
recode it.  These patches *remove* support for apache 1.0.x.

Its only lightly tested but works for me!  My indentation is 
different so you may well need -l swith to patch to apply it.

	Nigel.


--===_0_Mon_Jun_24_15:54:44_BST_1996
Content-Type: application/x-patch
Content-Description: mod_fastcgi.patch

--- ../../apache-fastcgi/src/mod_fastcgi.c	Tue Jun  4 16:08:04 1996
+++ mod_fastcgi.c	Mon Jun 24 15:30:06 1996
@@ -57,13 +57,6 @@
 char * translateName(WS_Request *r, char *uri, char *fullpath);
 void add_cgi_vars(WS_Request *r);
 void timeout(int);
-#if (APACHEVERSION < 11)
-#define FILE_BUFF(x) x->connection->request_in
-int GetFromStream(FILE *fp, char **buf);
-#else
-#define FILE_BUFF(x) x->connection->client
-int GetFromStream(BUFF *bp, char **buf);
-#endif
 #define WS_TimeOut(x)  timeout(x)
 #define HostInfo(x) x->server
 #define HostName(x) x->server->server_hostname
@@ -437,7 +430,6 @@
 FastCgiInfo *globalInfoPtr = NULL;
 int ht_openmax = 128;
 FILE *errorLogFd = NULL;
-void PrepareClientSocket(WS_Request *reqPtr, int *csdIn, int *csdOut);
 void MakeExtraEnvStr(WS_Request *reqPtr);
 void SetErrorLogFd(void *inp, int type);
 int WS_Access(const char *path, int mode);
@@ -2282,7 +2274,6 @@
   struct timeval timeOut;
   int clientRead, fcgiRead;
   int nBytes;
-  int csdIn, csdOut;
   int contentLength;
   char *lenp;
   int done = 0;
@@ -2291,12 +2282,13 @@
   FD_ZERO(&read_set);
   FD_ZERO(&write_set);
   numFDs = infoPtr->fd + 1;
-  timeOut.tv_sec = timeOut.tv_usec = 0;
+    timeOut.tv_sec = 0;
+    timeOut.tv_usec = 100000;
   lenp = table_get (reqPtr->headers_in, "Content-length");
   contentLength = (lenp) ? atoi(lenp) : 0;
   if (contentLength <= 0)
     clientRead = 0;
-  PrepareClientSocket(reqPtr, &csdIn, &csdOut);
+
   while (!done) {
 
     if(BufferLength(infoPtr->outbufPtr))
@@ -2305,14 +2297,9 @@
       FD_CLR(infoPtr->fd, &write_set);
 
     FD_SET(infoPtr->fd, &read_set);
-    FD_SET(csdIn, &read_set);
-
-    if(BufferLength(infoPtr->reqOutbufPtr))
-      FD_SET(csdOut, &write_set);
-    else
-      FD_CLR(csdOut, &write_set);
 
     select_status = select(numFDs, &read_set, &write_set, NULL, &timeOut);
+	/*      select_status = select(numFDs, &read_set, &write_set, NULL, NULL); */
     if(select_status < 0)
       break;
 
@@ -2321,7 +2308,20 @@
      * socket, until we can do no more work without blocking.
      */
     ClientToCgiBuffer(infoPtr);
+
+
+	/*
+	 * Move data between the buffers and the network sockets.
+	 */
+	if (FD_ISSET(infoPtr->fd, &read_set) && 
+	    (BufferFree(infoPtr->inbufPtr) > 0) &&
+	    infoPtr->fd >= 0) {
+	    if (BufferRead(infoPtr->inbufPtr, infoPtr->fd) <= 0)
+		fcgiRead = 0;
+
     CgiToClientBuffer(infoPtr);
+	}
+
 
     if(infoPtr->parseHeader == TRUE) {
         if(ScanCGIHeader(reqPtr, infoPtr) == FALSE) {
@@ -2334,55 +2334,39 @@
     }
 
 
-    if (nFirst) {
-      char *szBuf = NULL;
 
-      nBytes=GetFromStream(FILE_BUFF(reqPtr), &szBuf);
-      if (nBytes > 0) {
-	BufferAddData(infoPtr->reqInbufPtr, szBuf, nBytes);
+	if (BufferLength(infoPtr->reqOutbufPtr) > 0) {
+	    char outbuf[MAX_STRING_LEN];
+	    int gotbytes = BufferGetData(infoPtr->reqOutbufPtr, 
+					 outbuf, MAX_STRING_LEN);
+	    bwrite(reqPtr->connection->client, outbuf, gotbytes);
+	}
+
+	if (FD_ISSET(infoPtr->fd, &write_set)) {
+	    if (BufferFree(infoPtr->outbufPtr) > 0) {
+		/* Can output, but nothing in buffer - go for input! */
+		if (contentLength >= 0) {
+		    char inbuf[MAX_STRING_LEN];
+		    int readlen = min(MAX_STRING_LEN, contentLength);
+		    readlen = bread(reqPtr->connection->client, inbuf, readlen);
+
+		    if (readlen > 0) {
+			BufferAddData(infoPtr->reqInbufPtr, inbuf, readlen);
 	ClientToCgiBuffer(infoPtr);
+			contentLength -= readlen;
       }
-      if (szBuf)
-	free(szBuf);
-      nFirst = 0;
-      contentLength -= nBytes;
-      if (contentLength <= 0)
-	clientRead = 0;
     }
-
-    /*
-     * Move data between the buffers and the network sockets.
-     */
-    if(FD_ISSET(csdIn, &read_set) &&
-       (BufferFree(infoPtr->reqInbufPtr) > 0)) {
-      nBytes = BufferRead(infoPtr->reqInbufPtr, csdIn);
-      if (nBytes >= 0)
-	contentLength -= nBytes;
-      if (contentLength <= 0)
-	clientRead = 0;
     }
 
-    if(FD_ISSET(infoPtr->fd, &read_set) && 
-       (BufferFree(infoPtr->inbufPtr) > 0) &&
-       infoPtr->fd >= 0) {
-      if (BufferRead(infoPtr->inbufPtr, infoPtr->fd) <= 0)
-	fcgiRead = 0;
+	    if ((BufferLength(infoPtr->outbufPtr) > 0) &&
+		(infoPtr->fd >= 0)) {
+		BufferWrite(infoPtr->outbufPtr, infoPtr->fd);
     }
-
-    if(FD_ISSET(csdOut, &write_set) &&
-       (BufferLength(infoPtr->reqOutbufPtr) > 0)) {
-      BufferWrite(infoPtr->reqOutbufPtr, csdOut);
     }
 
-    if(FD_ISSET(infoPtr->fd, &write_set) &&
-       (BufferLength(infoPtr->outbufPtr) > 0) &&
-       infoPtr->fd >= 0) {
-      BufferWrite(infoPtr->outbufPtr, infoPtr->fd);
-    }
     if (fcgiRead)
       fcgiRead = (!infoPtr->exitStatusSet);
-    if (((clientRead == 0) ||
-	 !FD_ISSET(csdIn, &read_set)) &&
+	if ((contentLength <= 0) &&
 	(fcgiRead == 0) && 
 	(BufferLength(infoPtr->reqOutbufPtr) <= 0) &&
 	(BufferLength(infoPtr->outbufPtr) <= 0)) {
@@ -3392,69 +3376,7 @@
 }
 
 
-void PrepareClientSocket(WS_Request *reqPtr, int *csdIn, int *csdOut)
-{
-#if (APACHEVERSION <11)
-  fflush(reqPtr->connection->client);
-  *csdIn = fileno (reqPtr->connection->request_in);
-  *csdOut = fileno (reqPtr->connection->client);
-#else
-  bflush(reqPtr->connection->client);
-  *csdOut = reqPtr->connection->client->fd;
-  if (reqPtr->connection->client->fd_in != reqPtr->connection->client->fd)
-      *csdIn = reqPtr->connection->client->fd_in;
-  else
-      *csdIn = reqPtr->connection->client->fd;
-#endif
-}
-#if (APACHEVERSION < 11)
-
-/*
- *----------------------------------------------------------------------
- *
- * GetStreamSize 
- *    return the current buffer size of FILE structure
- *    OS dependent code, 
- *
- * Input: 
- *        
- * 
- * Results:
- *	
- *
- * Side effects:
- *	
- *
- *----------------------------------------------------------------------
- */
-int GetStreamSize(FILE *fp)
-{
-  return fp->_cnt;
-}
 
-int GetFromStream(FILE *fp, char **buf)
-{
-  int fp_size;
-  fp_size = GetStreamSize(fp);
-  *buf = NULL;
-  if (fp_size > 0) {
-    *buf = (char *) Malloc(fp_size+1);
-    fread(*buf, sizeof(char), fp_size, fp);
-  }
-  return fp_size;
-}
-#else
-int GetFromStream(BUFF *bp, char **buf)
-{
-  int bp_size;
-  bp_size = bp->incnt;
-  if (bp_size > 0) {
-    *buf = (char *) Malloc(bp_size+1);
-    bread(bp, *buf, bp_size);
-  }
-  return bp_size;
-}
-#endif
 
 void MakeExtraEnvStr(WS_Request *reqPtr)
 {

--===_0_Mon_Jun_24_15:54:44_BST_1996
Content-Type: text/plain; charset=us-ascii

[ Nigel.Metheringham@theplanet.net   - Unix Applications Engineer ]
[ *Views expressed here are personal and not supported by PLAnet* ]
[ PLAnet Online : The White House          Tel : +44 113 251 6012 ]
[ Melbourne Street, Leeds LS2 7PS UK.      Fax : +44 113 2345656  ]

--===_0_Mon_Jun_24_15:54:44_BST_1996--