[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[myserver-commit] [2891] Don' t use a temporary file to cache the FastCG
From: |
Giuseppe Scrivano |
Subject: |
[myserver-commit] [2891] Don' t use a temporary file to cache the FastCGI server reply but forward directly to the client . |
Date: |
Sun, 19 Oct 2008 15:30:21 +0000 |
Revision: 2891
http://svn.sv.gnu.org/viewvc/?view=rev&root=myserver&revision=2891
Author: gscrivano
Date: 2008-10-19 15:30:12 +0000 (Sun, 19 Oct 2008)
Log Message:
-----------
Don't use a temporary file to cache the FastCGI server reply but forward
directly to the client. Removed polling from `Socket::recv' when a timeout is
specified.
Modified Paths:
--------------
trunk/myserver/include/http_handler/fastcgi/fastcgi.h
trunk/myserver/src/base/socket/socket.cpp
trunk/myserver/src/http_handler/fastcgi/fastcgi.cpp
Modified: trunk/myserver/include/http_handler/fastcgi/fastcgi.h
===================================================================
--- trunk/myserver/include/http_handler/fastcgi/fastcgi.h 2008-10-18
21:02:37 UTC (rev 2890)
+++ trunk/myserver/include/http_handler/fastcgi/fastcgi.h 2008-10-19
15:30:12 UTC (rev 2891)
@@ -149,31 +149,46 @@
HttpThreadContext* td;
FastCgiServer* server;
Socket sock;
- File tempOut;
+
+ bool useChunks;
+ bool keepalive;
+ bool headerSent;
};
+class FiltersChain;
+
class FastCgi : public HttpDataHandler
{
public:
- static int getTimeout();
- static void setTimeout(int);
- FastCgi();
- static int load(XmlParser*);
- virtual int send(HttpThreadContext* td, ConnectionPtr connection,
+ static int getTimeout ();
+ static void setTimeout (int);
+ FastCgi ();
+ static int load (XmlParser*);
+ virtual int send (HttpThreadContext* td, ConnectionPtr connection,
const char* scriptpath, const char *cgipath,
int execute = 0, int onlyHeader = 0);
- static int unLoad();
+ static int unLoad ();
private:
static ProcessServerManager *processServerManager;
static int timeout;
static int initialized;
- void generateFcgiHeader( FcgiHeader&, int ,int, int );
- Socket getFcgiConnection();
- int buildFASTCGIEnvironmentString(HttpThreadContext*,char*,char*);
- int sendFcgiBody(FcgiContext* con, char* buffer, int len, int type, int
id);
- FastCgiServer* isFcgiServerRunning(const char*);
- FastCgiServer* runFcgiServer(FcgiContext*, const char*);
- FastCgiServer* connect(FcgiContext*, const char*);
+ int handleHeader (FcgiContext* con, FiltersChain* chain,
+ bool *responseCompleted);
+ int sendData (FcgiContext* con, u_long dim,
+ u_long timeout, FiltersChain* chain,
+ bool *responseCompleted, int onlyHeader);
+ int fastCgiRequest (FcgiContext* con, int id);
+ int readHeader (FcgiContext *con, FcgiHeader* header,
+ u_long started, u_long timeout, int id);
+
+
+ void generateFcgiHeader ( FcgiHeader&, int ,int, int );
+ Socket getFcgiConnection ();
+ int buildFASTCGIEnvironmentString (HttpThreadContext*,char*,char*);
+ int sendFcgiBody (FcgiContext* con, char* buffer, int len, int type,
int id);
+ FastCgiServer* isFcgiServerRunning (const char*);
+ FastCgiServer* runFcgiServer (FcgiContext*, const char*);
+ FastCgiServer* connect (FcgiContext*, const char*);
};
#endif
Modified: trunk/myserver/src/base/socket/socket.cpp
===================================================================
--- trunk/myserver/src/base/socket/socket.cpp 2008-10-18 21:02:37 UTC (rev
2890)
+++ trunk/myserver/src/base/socket/socket.cpp 2008-10-19 15:30:12 UTC (rev
2891)
@@ -622,18 +622,12 @@
*/
int Socket::recv(char* buffer, int len, int flags, u_long timeout)
{
- u_long time = getTicks();
- while(getTicks() - time < timeout)
- {
- /*! Check if there is data to read before do it. */
- if(bytesToRead())
- return recv(buffer, len, flags);
- }
- return 0;
+ if (dataOnRead (timeout / 1000, timeout % 1000))
+ return recv(buffer, len, flags);
+ return 0;
}
-
/*!
*Receive data from the socket.
*Returns -1 on errors.
Modified: trunk/myserver/src/http_handler/fastcgi/fastcgi.cpp
===================================================================
--- trunk/myserver/src/http_handler/fastcgi/fastcgi.cpp 2008-10-18 21:02:37 UTC
(rev 2890)
+++ trunk/myserver/src/http_handler/fastcgi/fastcgi.cpp 2008-10-19 15:30:12 UTC
(rev 2891)
@@ -62,10 +62,10 @@
int execute, int onlyHeader)
{
FcgiContext con;
- FcgiBeginRequestBody tBody;
u_long nbr = 0;
FcgiHeader header;
FiltersChain chain;
+ u_long nbw;
u_long headerSize = 0;
@@ -74,9 +74,6 @@
clock_t initialTicks;
- string outDataPath;
-
- int sizeEnvString;
FastCgiServer* server = 0;
int id;
ostringstream cmdLine;
@@ -84,13 +81,11 @@
string moreArg;
- bool useChunks = false;
- bool keepalive = false;
+ con.useChunks = false;
+ con.keepalive = false;
- /*! Size of data chunks to use with STDIN. */
- const size_t maxStdinChunk = 8192;
-
con.td = td;
+ con.headerSent = false;
td->scriptPath.assign(scriptpath);
@@ -105,24 +100,20 @@
chain.setProtocol(td->http);
chain.setProtocolData(td);
chain.setStream(td->connection->socket);
- if(td->mime)
+
+ if(td->mime && Server::getInstance()->getFiltersFactory()->chain(&chain,
+
td->mime->filters,
+
td->connection->socket,
+ &nbw,
+ 1))
{
- u_long nbw;
- if(td->mime && Server::getInstance()->getFiltersFactory()->chain(&chain,
- td->mime->filters,
- td->connection->socket,
- &nbw,
- 1))
- {
- td->connection->host->warningsLogWrite(
- "FastCGI: Error loading filters");
- chain.clearAllFilters();
- return td->http->raiseHTTPError(500);
- }
+ td->connection->host->warningsLogWrite("FastCGI: Error loading filters");
+ chain.clearAllFilters();
+ return td->http->raiseHTTPError(500);
}
- td->buffer->setLength(0);
- td->buffer2->getAt(0) = '\0';
+ td->buffer->setLength (0);
+ td->buffer2->getAt (0) = '\0';
{
@@ -200,20 +191,6 @@
#endif
}
- Env::buildEnvironmentString(td, td->buffer->getBuffer());
- sizeEnvString = buildFASTCGIEnvironmentString(td,td->buffer->getBuffer(),
- td->buffer2->getBuffer());
- if(sizeEnvString == -1)
- {
- td->buffer->setLength(0);
- if(Server::getInstance()->getVerbosity() > 2)
- {
- *td->buffer << "FastCGI: Error to build env string" << '\0';
- td->connection->host->warningsLogWrite(td->buffer->getBuffer());
- }
- chain.clearAllFilters();
- return td->http->raiseHTTPError(500);
- }
td->inputData.close();
if(td->inputData.openFile(td->inputDataPath, File::MYSERVER_OPEN_READ |
File::MYSERVER_OPEN_ALWAYS |
@@ -229,12 +206,12 @@
return td->http->raiseHTTPError(500);
}
- server = connect(&con, cmdLine.str().c_str());
+ server = connect (&con, cmdLine.str().c_str());
- if(server == 0)
+ if (server == 0)
{
- td->buffer->setLength(0);
- if(Server::getInstance()->getVerbosity() > 2)
+ td->buffer->setLength (0);
+ if(Server::getInstance ()->getVerbosity () > 2)
{
*td->buffer << "FastCGI: Error connecting to FastCGI "
<< cmdLine.str().c_str() << " process" << '\0';
@@ -245,118 +222,12 @@
}
id = td->id + 1;
- tBody.roleB1 = ( FCGIRESPONDER >> 8 ) & 0xff;
- tBody.roleB0 = ( FCGIRESPONDER ) & 0xff;
- tBody.flags = 0;
- memset( tBody.reserved, 0, sizeof( tBody.reserved ) );
- if(sendFcgiBody(&con, (char*)&tBody, sizeof(tBody), FCGIBEGIN_REQUEST, id))
+ if (fastCgiRequest (&con, id))
{
- td->buffer->setLength(0);
- if(Server::getInstance()->getVerbosity() > 2)
- {
- *td->buffer<< "FastCGI: Error beginning the request" << '\0';
- td->connection->host->warningsLogWrite(td->buffer->getBuffer());
- }
- chain.clearAllFilters();
- con.sock.close();
return td->http->raiseHTTPError(500);
}
- if(sendFcgiBody(&con,td->buffer2->getBuffer(), sizeEnvString,
- FCGIPARAMS, id))
- {
- td->buffer->setLength(0);
- if(Server::getInstance()->getVerbosity() > 2)
- {
- *td->buffer << "FastCGI: Error sending params" << '\0';
- td->connection->host->warningsLogWrite(td->buffer->getBuffer());
- }
- chain.clearAllFilters();
- con.sock.close();
- return td->http->raiseHTTPError(501);
- }
-
- if(sendFcgiBody(&con, 0, 0, FCGIPARAMS, id))
- {
- td->buffer->setLength(0);
- if(Server::getInstance()->getVerbosity() > 2)
- {
- *td->buffer << "FastCGI: Error sending params" << '\0';
- td->connection->host->warningsLogWrite(td->buffer->getBuffer());
- }
- chain.clearAllFilters();
- con.sock.close();
- return td->http->raiseHTTPError(500);
- }
-
- if(atoi(td->request.contentLength.c_str()))
- {
- td->buffer->setLength(0);
-
-
- if(td->inputData.setFilePointer(0))
- if(Server::getInstance()->getVerbosity() > 2)
- {
- *td->buffer << "FastCGI: Error sending POST data" << '\0';
- td->connection->host->warningsLogWrite(td->buffer->getBuffer());
- }
-
- /*! Send the STDIN data. */
- do
- {
- if(td->inputData.readFromFile(td->buffer->getBuffer(),
- maxStdinChunk, &nbr))
- {
- td->buffer->setLength(0);
- if(Server::getInstance()->getVerbosity() > 2)
- {
- *td->buffer << "FastCGI: Error reading from file" << '\0';
- td->connection->host->warningsLogWrite(
- td->buffer->getBuffer());
- }
- return td->http->sendHTTPhardError500();
- }
-
- if(!nbr)
- break;
-
- generateFcgiHeader( header, FCGISTDIN, id, nbr);
- if(con.sock.send((char*)&header, sizeof(header), 0) == -1)
- {
- chain.clearAllFilters();
- return td->http->raiseHTTPError(501);
- }
-
- if(con.sock.send(td->buffer->getBuffer(),nbr,0) == -1)
- {
- td->buffer->setLength(0);
- if(Server::getInstance()->getVerbosity() > 2)
- {
- *td->buffer << "FastCGI: Error sending data" << '\0';
- td->connection->host->warningsLogWrite(td->buffer->getBuffer());
- }
- chain.clearAllFilters();
- return td->http->raiseHTTPError(500);
- }
- }while(nbr == maxStdinChunk);
- }
-
- /*! Final stdin chunk. */
- if(sendFcgiBody(&con, 0, 0, FCGISTDIN, id))
- {
- td->buffer->setLength(0);
- if(Server::getInstance()->getVerbosity() > 2)
- {
- *td->buffer << "FastCGI: Error sending POST data" << '\0';
- td->connection->host->
- warningsLogWrite(td->buffer->getBuffer());
-
- }
- con.sock.close();
- return td->http->raiseHTTPError(500);
- }
-
/*! Now read the output. This flag is used by the external loop. */
exit = 0;
@@ -365,53 +236,21 @@
initialTicks = getTicks();
- FilesUtility::temporaryFileName(td->id, outDataPath);
+ td->buffer->setLength(0);
+ checkDataChunks(td, &con.keepalive, &con.useChunks);
- if(con.tempOut.createTemporaryFile(outDataPath.c_str()))
- {
- td->buffer->setLength(0);
- *td->buffer << "FastCGI: Error opening stdout file" << '\0';
- td->connection->host->warningsLogWrite(td->buffer->getBuffer());
- return td->http->raiseHTTPError(500);
- }
-
do
{
u_long dim;
- u_long dataSent;
u_long nbw;
-
- while(con.sock.bytesToRead() < sizeof(FcgiHeader))
+
+ if (readHeader (&con, &header, initialTicks, timeout, id))
{
- if((clock_t)(getTicks() - initialTicks) > timeout)
- break;
- con.sock.dataOnRead (timeout / 1000, timeout % 1000);
- }
-
- if(con.sock.bytesToRead() >= sizeof(FcgiHeader))
- {
- nbr = con.sock.recv((char*)&header, sizeof(FcgiHeader), 0,
- static_cast<u_long>(timeout));
- if(nbr != sizeof(FcgiHeader))
- {
- td->buffer->setLength(0);
- *td->buffer << "FastCGI: Error reading data" << '\0';
- td->connection->host->warningsLogWrite(td->buffer->getBuffer());
- sendFcgiBody(&con, 0, 0, FCGIABORT_REQUEST, id);
- ret = 0;
- break;
- }
- }
- else
- {
- td->buffer->setLength(0);
- *td->buffer << "FastCGI: Error timeout" << '\0';
- td->connection->host->warningsLogWrite(td->buffer->getBuffer());
- sendFcgiBody(&con, 0, 0, FCGIABORT_REQUEST, id);
- con.sock.shutdown(2);
- con.sock.close();
+ exit = 1;
+ ret = 1;
break;
}
+
/*!
*contentLengthB1 is the high word of the content length value
*while contentLengthB0 is the low one.
@@ -419,7 +258,7 @@
*of eight byte then do an or with contentLengthB0.
*/
dim = (header.contentLengthB1 << 8) | header.contentLengthB0;
- dataSent = 0;
+
if(dim == 0)
{
exit = 1;
@@ -427,6 +266,8 @@
}
else
{
+ bool headerCompleted = false;
+
switch(header.type)
{
case FCGISTDERR:
@@ -436,28 +277,21 @@
ret = 0;
break;
case FCGISTDOUT:
- dataSent = 0;
+ headerCompleted = false;
+ ret = sendData (&con, dim, static_cast<u_long>(timeout), &chain,
+ &headerCompleted, onlyHeader);
- while(dataSent < dim)
+ if (ret)
{
- nbr = con.sock.recv(td->buffer->getBuffer(),
-
std::min(static_cast<u_long>(td->buffer->getRealLength()),
- dim - dataSent), 0,
static_cast<u_long>(timeout));
- if(nbr == (u_long)-1)
- {
- exit = 1;
- ret = 0;
- break;
- }
+ exit = 1;
+ ret = 0;
+ break;
+ }
- if(con.tempOut.writeToFile((char*)(td->buffer->getBuffer()),
- nbr, &nbw))
- {
- exit = 1;
- ret = 0;
- break;
- }
- dataSent += nbr;
+ if (headerCompleted)
+ {
+ exit = 1;
+ break;
}
break;
@@ -474,12 +308,12 @@
if(header.paddingLength)
{
u_long toPad = header.paddingLength;
- while(toPad)
+ while (toPad)
{
nbr = con.sock.recv(td->buffer->getBuffer(),
std::min(toPad,
(u_long)td->buffer->getRealLength()), 0,
static_cast<u_long>(timeout));
- if(nbr == (u_long)-1)
+ if (nbr == (u_long)-1)
{
exit = 1;
ret = 0;
@@ -488,208 +322,16 @@
toPad -= nbr;
}
}
+ }while (!exit);
- }while((!exit) && nbr);
+ /* Send the last null chunk if needed. */
+ if((td->response.getStatusType () == HttpResponseHeader::SUCCESSFUL) &&
+ con.useChunks && chain.write("0\r\n\r\n", 5, &nbw))
+ return 0;
- con.tempOut.setFilePointer(0);
- td->buffer->getAt(0) = '\0';
- buffer = td->buffer->getBuffer();
-
-
-
- /*! Return an error message if ret is 0. */
- if((!ret) || con.tempOut.readFromFile(buffer,
- td->buffer->getRealLength(), &nbr))
- {
- con.tempOut.close();
- FilesUtility::deleteFile(outDataPath.c_str());
- con.sock.close();
- chain.clearAllFilters();
- return td->http->sendHTTPhardError500();
- }
-
- /*!
- *find the \r\n\r\n sequence.
- */
- for(u_long i = 0; i < nbr; i++)
- {
- if((buffer[i] == '\r') && (buffer[i + 1] == '\n') &&
- (buffer[i + 2] == '\r') && (buffer[i + 3] == '\n'))
- {
- headerSize = i + 4 ;
- break;
- }
- }
-
- /* For logging. */
- td->sentData += con.tempOut.getFileSize() - headerSize;
-
- HttpHeaders::buildHTTPResponseHeaderStruct(td->buffer->getBuffer(),
- &td->response,
- &(td->nBytesToRead));
-
-
- for(;;)
- {
- u_long nbw2;
- if(td->response.location[0])
- {
- con.tempOut.close();
- FilesUtility::deleteFile(outDataPath.c_str());
- con.sock.close();
- chain.clearAllFilters();
- return td->http->sendHTTPRedirect((char*)td->response.location.c_str());
- }
- /*! Send the header. */
- if(!td->appendOutputs)
- {
- checkDataChunks(td, &keepalive, &useChunks);
-
- HttpHeaders::buildHTTPResponseHeader(td->buffer2->getBuffer(),
- &td->response);
- if(td->connection->socket->send( td->buffer2->getBuffer(),
- static_cast<int>(strlen(td->buffer2->getBuffer())),
- 0) == SOCKET_ERROR )
- {
- exit = 1;
- ret = 0;
- break;
- }
-
- if(onlyHeader)
- {
- exit = 1;
- ret = 1;
- break;
- }
-
- if(nbr - headerSize)
- {
- if(useChunks)
- {
- ostringstream tmp;
- tmp << hex << (nbr - headerSize) << "\r\n";
- td->response.contentLength.assign(tmp.str());
- if(chain.write(tmp.str().c_str(), tmp.str().length(), &nbw2))
- {
- exit = 0;
- ret = 0;
- break;
- }
- }
-
- if(chain.write((char*)((td->buffer->getBuffer())
- +headerSize), nbr - headerSize, &nbw2))
- {
- exit = 0;
- ret = 0;
- break;
- }
-
- if(useChunks && chain.write("\r\n", 2, &nbw2))
- {
- exit = 0;
- ret = 0;
- break;
- }
- }
- }
- else/*! If appendOutputs. */
- {
- u_long nbw = 0;
- if(onlyHeader)
- {
- exit = 1;
- ret = 1;
- break;
- }
-
- /*!
- *Send remaining data stored in the buffer.
- *This is the HTTP header.
- */
- if(td->outputData.writeToFile((char*)((td->buffer2->getBuffer())
- + headerSize), nbr - headerSize,
- &nbw))
- {
- exit = 1;
- ret = 0;
- break;
- }
- }
-
- if (td->response.getStatusType () == HttpResponseHeader::SUCCESSFUL)
- {
- /*! Flush the data. */
- do
- {
- if(con.tempOut.readFromFile(td->buffer->getBuffer(),
- td->buffer->getRealLength(), &nbr))
- {
- exit = 1;
- ret = 0;
- break;
- }
-
- if(!td->appendOutputs)
- {
- u_long nbw2;
- if(nbr)
- {
- if(useChunks)
- {
- ostringstream tmp;
- tmp << hex << nbr << "\r\n";
- td->response.contentLength.assign(tmp.str());
- if(chain.write(tmp.str().c_str(), tmp.str().length(), &nbw2))
- {
- exit = 1;
- ret = 0;
- break;
- }
- }
-
- if(chain.write(td->buffer->getBuffer(), nbr, &nbw2))
- {
- exit = 1;
- ret = 0;
- break;
- }
-
- if(useChunks && chain.write("\r\n", 2, &nbw2))
- {
- exit = 1;
- ret = 0;
- break;
- }
- }
- }
- else
- {
- u_long nbw = 0;
- if(td->outputData.writeToFile(td->buffer->getBuffer(), nbr, &nbw))
- {
- exit = 1;
- ret = 0;
- break;
- }
- }
- }while(nbr);
-
- if(useChunks && chain.write("0\r\n\r\n", 5, &nbw2))
- {
- exit = 1;
- ret = 0;
- break;
- }
- }
-
- break;
- }
chain.clearAllFilters();
- con.tempOut.close();
- FilesUtility::deleteFile(outDataPath.c_str());
con.sock.close();
+
return ret;
}
@@ -911,3 +553,329 @@
{
timeout = ntimeout;
}
+
+/*!
+ *Do a request to the FastCGI server.
+ *\param con The current FastCGI context.
+ *\param id The request ID.
+ */
+int FastCgi::fastCgiRequest (FcgiContext* con, int id)
+{
+ FcgiBeginRequestBody tBody;
+ HttpThreadContext *td = con->td;
+ /*! Size of data chunks to use with STDIN. */
+ const size_t maxStdinChunk = 8192;
+ u_long nbr;
+ FcgiHeader header;
+ int sizeEnvString;
+
+ Env::buildEnvironmentString(td, td->buffer->getBuffer());
+ sizeEnvString = buildFASTCGIEnvironmentString(td,td->buffer->getBuffer(),
+ td->buffer2->getBuffer());
+ if(sizeEnvString == -1)
+ {
+ td->buffer->setLength(0);
+ if(Server::getInstance()->getVerbosity() > 2)
+ {
+ *td->buffer << "FastCGI: Error to build env string" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+ }
+ return 1;
+ }
+
+
+ tBody.roleB1 = ( FCGIRESPONDER >> 8 ) & 0xff;
+ tBody.roleB0 = ( FCGIRESPONDER ) & 0xff;
+ tBody.flags = 0;
+ memset( tBody.reserved, 0, sizeof( tBody.reserved ) );
+
+ if(sendFcgiBody(con, (char*)&tBody, sizeof(tBody), FCGIBEGIN_REQUEST, id))
+ {
+ td->buffer->setLength(0);
+ if(Server::getInstance()->getVerbosity() > 2)
+ {
+ *td->buffer<< "FastCGI: Error beginning the request" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+ }
+ return 1;
+ }
+
+ if(sendFcgiBody(con, td->buffer2->getBuffer(), sizeEnvString,
+ FCGIPARAMS, id))
+ {
+ td->buffer->setLength(0);
+ if(Server::getInstance()->getVerbosity() > 2)
+ {
+ *td->buffer << "FastCGI: Error sending params" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+ }
+ return 1;
+ }
+
+ if(sendFcgiBody(con, 0, 0, FCGIPARAMS, id))
+ {
+ td->buffer->setLength(0);
+ if(Server::getInstance()->getVerbosity() > 2)
+ {
+ *td->buffer << "FastCGI: Error sending params" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+ }
+ return 1;
+ }
+
+ if(atoi(td->request.contentLength.c_str()))
+ {
+ td->buffer->setLength(0);
+
+
+ if(td->inputData.setFilePointer(0))
+ if(Server::getInstance()->getVerbosity() > 2)
+ {
+ *td->buffer << "FastCGI: Error sending POST data" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+ }
+
+ /*! Send the STDIN data. */
+ do
+ {
+ if(td->inputData.readFromFile(td->buffer->getBuffer(),
+ maxStdinChunk, &nbr))
+ {
+ td->buffer->setLength(0);
+ if(Server::getInstance()->getVerbosity() > 2)
+ {
+ *td->buffer << "FastCGI: Error reading from file" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+ }
+ return 1;
+ }
+
+ if(!nbr)
+ break;
+
+ generateFcgiHeader( header, FCGISTDIN, id, nbr);
+ if(con->sock.send((char*)&header, sizeof(header), 0) == -1)
+ {
+ return 1;
+ }
+
+ if(con->sock.send(td->buffer->getBuffer(),nbr,0) == -1)
+ {
+ td->buffer->setLength(0);
+ if(Server::getInstance()->getVerbosity() > 2)
+ {
+ *td->buffer << "FastCGI: Error sending data" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+ }
+ return 1;
+ }
+ }while(nbr == maxStdinChunk);
+ }
+
+ /*! Final stdin chunk. */
+ if(sendFcgiBody(con, 0, 0, FCGISTDIN, id))
+ {
+ td->buffer->setLength(0);
+ if(Server::getInstance()->getVerbosity() > 2)
+ {
+ *td->buffer << "FastCGI: Error sending POST data" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/*!
+ *Handle the STDOUT data received from the FastCGI server.
+ *The FastCGI header must be read previously, only the payload is processed
here.
+ *\param con The current FastCGI context.
+ *\param dim Size of the payload.
+ *\param timeout Connection timeout to use.
+ *\param chain Output chain where to send data.
+ *\param responseCompleted Output value. It is true when the response is
completed.
+ *\param onlyHeader Send only the HTTP header.
+ *\return 0 on success.
+ */
+int FastCgi::sendData (FcgiContext* con, u_long dim, u_long timeout,
FiltersChain* chain,
+ bool *responseCompleted, int onlyHeader)
+{
+ u_long dataRead = 0;
+ while (dataRead < dim)
+ {
+ HttpThreadContext* td = con->td;
+
+ if (con->headerSent)
+ {
+ td->buffer->setLength (0);
+ }
+
+ if (dim - td->buffer->getLength () == 0)
+ {
+ return 1;
+ }
+
+ u_long nbr = con->sock.recv (td->buffer->getBuffer () +
td->buffer->getLength (),
+ std::min ((u_long)td->buffer->getRealLength
(),
+ dim - td->buffer->getLength ()),
+ 0, timeout);
+ if (nbr == (u_long)-1 || nbr == 0)
+ {
+ return 1;
+ }
+
+ td->buffer->setLength (td->buffer->getLength () + nbr);
+
+ dataRead += nbr;
+
+ if (!con->headerSent)
+ {
+ return handleHeader (con, chain, responseCompleted);
+ }
+ }
+
+ if (onlyHeader || con->td->response.getStatusType () !=
HttpResponseHeader::SUCCESSFUL)
+ return 0;
+
+ if(HttpDataHandler::appendDataToHTTPChannel(con->td,
+ con->td->buffer->getBuffer (),
+ con->td->buffer->getLength (),
+ &(con->td->outputData),
+ chain,
+ con->td->appendOutputs,
+ con->useChunks))
+ return 1;
+
+ con->td->sentData += con->td->buffer->getLength ();
+
+ return 0;
+}
+
+/*!
+ *Look for a HTTP header in the fastcgi server data.
+ *\param con The current FastCGI context.
+ *\param chain Output chain where to send data.
+ *\param responseCompleted Output value. It is true when the response is
completed.
+ *\return 0 on success.
+ */
+int FastCgi::handleHeader (FcgiContext* con, FiltersChain* chain, bool*
responseCompleted)
+{
+ char* buffer = con->td->buffer->getBuffer ();
+ u_long size = con->td->buffer->getLength ();
+ u_long headerSize = 0;
+
+ for(u_long i = 0; i < size - 3; i++)
+ {
+ if((buffer[i] == '\r') && (buffer[i + 1] == '\n') &&
+ (buffer[i + 2] == '\r') && (buffer[i + 3] == '\n'))
+ {
+ headerSize = i + 4;
+ break;
+ }
+ }
+
+ if (headerSize == 0)
+ return 0;
+
+ HttpHeaders::buildHTTPResponseHeaderStruct(con->td->buffer->getBuffer(),
+ &con->td->response,
+ &(con->td->nBytesToRead));
+
+ if(!con->td->appendOutputs)
+ {
+ if(con->td->response.location[0])
+ {
+ *responseCompleted = true;
+
con->td->http->sendHTTPRedirect((char*)con->td->response.location.c_str());
+ return 0;
+ }
+
+ HttpHeaders::buildHTTPResponseHeader(con->td->buffer2->getBuffer(),
+ &con->td->response);
+
+ if(con->td->connection->socket->send(con->td->buffer2->getBuffer(),
+
static_cast<int>(strlen(con->td->buffer2->getBuffer())),
+ 0) == SOCKET_ERROR )
+ {
+ *responseCompleted = true;
+ return 1;
+ }
+
+ }
+
+ con->headerSent = true;
+
+ /* Flush the buffer if remaining data is present. */
+ if (con->td->response.getStatusType () == HttpResponseHeader::SUCCESSFUL &&
+ size - headerSize)
+ {
+ if(HttpDataHandler::appendDataToHTTPChannel(con->td,
+ con->td->buffer->getBuffer() +
headerSize,
+ size - headerSize,
+ &(con->td->outputData),
+ chain,
+ con->td->appendOutputs,
+ con->useChunks))
+ return 1;
+
+ con->td->sentData += size - headerSize;
+ }
+
+ return 0;
+}
+
+/*!
+ *Read a FastCGI header.
+ *\param con The FastCGI context.
+ *\param header The header to read.
+ *\param started Start time for the request (it is used to compute the
timeout).
+ *\param timeout The timeout to use for the connection.
+ *\param id Request ID.
+ *\return 0 on success.
+ */
+int FastCgi::readHeader (FcgiContext *con, FcgiHeader* header, u_long started,
u_long timeout, int id)
+{
+ u_long nbr;
+ HttpThreadContext* td = con->td;
+ char* buffer = (char*) header;
+ u_long readData = 0;
+
+ for (;;)
+ {
+ u_long ticks = getTicks ();
+
+ if (ticks - started > timeout)
+ {
+ td->buffer->setLength(0);
+ *td->buffer << "FastCGI: server timeout" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+ sendFcgiBody(con, 0, 0, FCGIABORT_REQUEST, id);
+ return 1;
+ }
+
+ nbr = con->sock.recv(buffer + readData, sizeof(FcgiHeader) - readData, 0,
+ timeout - (ticks - started));
+
+ if (nbr == static_cast<u_long>(-1) || nbr == 0)
+ return 1;
+
+ readData += nbr;
+
+ if (readData == sizeof (FcgiHeader))
+ break;
+
+ if (readData > sizeof (FcgiHeader))
+ {
+ td->buffer->setLength(0);
+ *td->buffer << "FastCGI: Error reading data" << '\0';
+ td->connection->host->warningsLogWrite(td->buffer->getBuffer());
+ sendFcgiBody(con, 0, 0, FCGIABORT_REQUEST, id);
+ return 1;
+ }
+ }
+
+ return 0;
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [myserver-commit] [2891] Don' t use a temporary file to cache the FastCGI server reply but forward directly to the client .,
Giuseppe Scrivano <=