📄 fcgiapp.c
字号:
if(headerLen < sizeof(header)) { continue; }; headerLen = 0; /* * Interpret header. eorStop prevents ProcessHeader from reading * past the end-of-record when using stream to read content. */ data->eorStop = TRUE; stream->stop = stream->rdNext; status = ProcessHeader(header, stream); data->eorStop = FALSE; stream->isClosed = FALSE; switch(status) { case STREAM_RECORD: /* * If this stream record header marked the end of stream * data deliver EOF to the stream client, otherwise loop * and deliver data. * * XXX: If this is final stream and * stream->rdNext != data->buffStop, buffered * data is next request (server pipelining)? */ if(data->contentLen == 0) { stream->wrNext = stream->stop = stream->rdNext; stream->isClosed = TRUE; return; } break; case SKIP: data->skip = TRUE; break; case BEGIN_RECORD: /* * If this header marked the beginning of a new * request, return role information to caller. */ return; break; case MGMT_RECORD: break; default: ASSERT(status < 0); SetError(stream, status); return; break; } }}/* *---------------------------------------------------------------------- * * NewStream -- * * Creates a stream to read or write from an open ipcFd. * The stream performs reads/writes of up to bufflen bytes. * *---------------------------------------------------------------------- */static FCGX_Stream *NewStream( FCGX_Request *reqDataPtr, int bufflen, int isReader, int streamType){ /* * XXX: It would be a lot cleaner to have a NewStream that only * knows about the type FCGX_Stream, with all other * necessary data passed in. It appears that not just * data and the two procs are needed for initializing stream, * but also data->buff and data->buffStop. This has implications * for procs that want to swap buffers, too. */ FCGX_Stream *stream = (FCGX_Stream *)Malloc(sizeof(FCGX_Stream)); FCGX_Stream_Data *data = (FCGX_Stream_Data *)Malloc(sizeof(FCGX_Stream_Data)); data->reqDataPtr = reqDataPtr; bufflen = AlignInt8(min(max(bufflen, 32), FCGI_MAX_LENGTH + 1)); data->bufflen = bufflen; data->mBuff = (unsigned char *)Malloc(bufflen); data->buff = AlignPtr8(data->mBuff); if(data->buff != data->mBuff) { data->bufflen -= 8; } if(isReader) { data->buffStop = data->buff; } else { data->buffStop = data->buff + data->bufflen; } data->type = streamType; data->eorStop = FALSE; data->skip = FALSE; data->contentLen = 0; data->paddingLen = 0; data->isAnythingWritten = FALSE; data->rawWrite = FALSE; stream->data = data; stream->isReader = isReader; stream->isClosed = FALSE; stream->wasFCloseCalled = FALSE; stream->FCGI_errno = 0; if(isReader) { stream->fillBuffProc = FillBuffProc; stream->emptyBuffProc = NULL; stream->rdNext = data->buff; stream->stop = stream->rdNext; stream->stopUnget = data->buff; stream->wrNext = stream->stop; } else { stream->fillBuffProc = NULL; stream->emptyBuffProc = EmptyBuffProc; stream->wrNext = data->buff + sizeof(FCGI_Header); stream->stop = data->buffStop; stream->stopUnget = NULL; stream->rdNext = stream->stop; } return stream;}/* *---------------------------------------------------------------------- * * FCGX_FreeStream -- * * Frees all storage allocated when *streamPtr was created, * and nulls out *streamPtr. * *---------------------------------------------------------------------- */void FCGX_FreeStream(FCGX_Stream **streamPtr){ FCGX_Stream *stream = *streamPtr; FCGX_Stream_Data *data; if(stream == NULL) { return; } data = (FCGX_Stream_Data *)stream->data; data->reqDataPtr = NULL; free(data->mBuff); free(data); free(stream); *streamPtr = NULL;}/* *---------------------------------------------------------------------- * * SetReaderType -- * * Re-initializes the stream to read data of the specified type. * *---------------------------------------------------------------------- */static FCGX_Stream *SetReaderType(FCGX_Stream *stream, int streamType){ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; ASSERT(stream->isReader); data->type = streamType; data->eorStop = FALSE; data->skip = FALSE; data->contentLen = 0; data->paddingLen = 0; stream->wrNext = stream->stop = stream->rdNext; stream->isClosed = FALSE; return stream;}/* *---------------------------------------------------------------------- * * NewReader -- * * Creates a stream to read streamType records for the given * request. The stream performs OS reads of up to bufflen bytes. * *---------------------------------------------------------------------- */static FCGX_Stream *NewReader(FCGX_Request *reqDataPtr, int bufflen, int streamType){ return NewStream(reqDataPtr, bufflen, TRUE, streamType);}/* *---------------------------------------------------------------------- * * NewWriter -- * * Creates a stream to write streamType FastCGI records, using * the ipcFd and RequestId contained in *reqDataPtr. * The stream performs OS writes of up to bufflen bytes. * *---------------------------------------------------------------------- */static FCGX_Stream *NewWriter(FCGX_Request *reqDataPtr, int bufflen, int streamType){ return NewStream(reqDataPtr, bufflen, FALSE, streamType);}/* *---------------------------------------------------------------------- * * FCGX_CreateWriter -- * * Creates a stream to write streamType FastCGI records, using * the given ipcFd and request Id. This function is provided * for use by cgi-fcgi. In order to be defensive against misuse, * this function leaks a little storage; cgi-fcgi doesn't care. * *---------------------------------------------------------------------- */FCGX_Stream *FCGX_CreateWriter( int ipcFd, int requestId, int bufflen, int streamType){ FCGX_Request *reqDataPtr = (FCGX_Request *)Malloc(sizeof(FCGX_Request)); reqDataPtr->ipcFd = ipcFd; reqDataPtr->requestId = requestId; /* * Suppress writing an FCGI_END_REQUEST record. */ reqDataPtr->nWriters = 2; return NewWriter(reqDataPtr, bufflen, streamType);}/* *====================================================================== * Control *====================================================================== *//* *---------------------------------------------------------------------- * * FCGX_IsCGI -- * * This routine determines if the process is running as a CGI or * FastCGI process. The distinction is made by determining whether * FCGI_LISTENSOCK_FILENO is a listener ipcFd or the end of a * pipe (ie. standard in). * * Results: * TRUE if the process is a CGI process, FALSE if FastCGI. * *---------------------------------------------------------------------- */int FCGX_IsCGI(void){ if (isFastCGI != -1) { return !isFastCGI; } if (!libInitialized) { int rc = FCGX_Init(); if (rc) { /* exit() isn't great, but hey */ exit((rc < 0) ? rc : -rc); } } isFastCGI = OS_IsFcgi(FCGI_LISTENSOCK_FILENO); return !isFastCGI;}/* *---------------------------------------------------------------------- * * FCGX_Finish -- * * Finishes the current request from the HTTP server. * * Side effects: * * Finishes the request accepted by (and frees any * storage allocated by) the previous call to FCGX_Accept. * * DO NOT retain pointers to the envp array or any strings * contained in it (e.g. to the result of calling FCGX_GetParam), * since these will be freed by the next call to FCGX_Finish * or FCGX_Accept. * *---------------------------------------------------------------------- */void FCGX_Finish(void){ FCGX_Finish_r(&the_request);}/* *---------------------------------------------------------------------- * * FCGX_Finish_r -- * * Finishes the current request from the HTTP server. * * Side effects: * * Finishes the request accepted by (and frees any * storage allocated by) the previous call to FCGX_Accept. * * DO NOT retain pointers to the envp array or any strings * contained in it (e.g. to the result of calling FCGX_GetParam), * since these will be freed by the next call to FCGX_Finish * or FCGX_Accept. * *---------------------------------------------------------------------- */void FCGX_Finish_r(FCGX_Request *reqDataPtr){ int close; if (reqDataPtr == NULL) { return; } close = !reqDataPtr->keepConnection; /* This should probably use a 'status' member instead of 'in' */ if (reqDataPtr->in) { close |= FCGX_FClose(reqDataPtr->err); close |= FCGX_FClose(reqDataPtr->out); close |= FCGX_GetError(reqDataPtr->in); } FCGX_Free(reqDataPtr, close);}void FCGX_Free(FCGX_Request * request, int close){ if (request == NULL) return; FCGX_FreeStream(&request->in); FCGX_FreeStream(&request->out); FCGX_FreeStream(&request->err); FreeParams(&request->paramsPtr); if (close) { OS_IpcClose(request->ipcFd); request->ipcFd = -1; }}int FCGX_OpenSocket(const char *path, int backlog){ int rc = OS_CreateLocalIpcFd(path, backlog); if (rc == FCGI_LISTENSOCK_FILENO && isFastCGI == 0) { /* XXX probably need to call OS_LibInit() again for Win */ isFastCGI = 1; } return rc;}int FCGX_InitRequest(FCGX_Request *request, int sock, int flags){ memset(request, 0, sizeof(FCGX_Request)); /* @@@ Should check that sock is open and listening */ request->listen_sock = sock; /* @@@ Should validate against "known" flags */ request->flags = flags; request->ipcFd = -1; return 0;}/* *---------------------------------------------------------------------- * * FCGX_Init -- * * Initilize the FCGX library. This is called by FCGX_Accept() * but must be called by the user when using FCGX_Accept_r(). * * Results: * 0 for successful call. * *---------------------------------------------------------------------- */int FCGX_Init(void){ char *p; if (libInitialized) { return 0; } FCGX_InitRequest(&the_request, FCGI_LISTENSOCK_FILENO, 0); if (OS_LibInit(NULL) == -1) { return OS_Errno ? OS_Errno : -9997; } p = getenv("FCGI_WEB_SERVER_ADDRS"); webServerAddressList = p ? StringCopy(p) : NULL; libInitialized = 1; return 0;}/* *---------------------------------------------------------------------- * * FCGX_Accept -- * * Accepts a new request from the HTTP server. * * Results: * 0 for successful call, -1 for error. * * Side effects: * * Finishes the request accepted by (and frees any * storage allocated by) the previous call to FCGX_Accept. * Creates input, output, and error streams and * assigns them to *in, *out, a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -