int FCGI_ferror(FCGI_FILE *fp) { if(fp->stdio_stream) { return ferror(fp->stdio_stream); } else if(fp->fcgx_stream) { return FCGX_GetError(fp->fcgx_stream); } return -1; }
/* Returns the number of bytes read, or -1 on error. */ static int readContentData(HTTPRequest *req, void *buffer, int dataSize, int mustFill) { WOLog (WO_INFO, "data size: %d", dataSize ); //int n = fread(buffer, 1, dataSize, stdin); int n = FCGX_GetStr(buffer, dataSize, in); if (n != dataSize) { //int err = ferror(stdin); int err = FCGX_GetError(in); if (err) WOLog(WO_ERR,"Error getting content data: %s (%d)", strerror(errno), err); } /* *((char*)buffer+dataSize) = '\0'; WOLog ( WO_INFO, "buffer: %s", (char *)buffer );*/ return n == dataSize ? n : -1; }
int FastcgiRequest::write(const char *buf, int size) { int num = FCGX_PutStr(buf, size, fcgiRequest_.out); if (-1 == num) { std::stringstream str; int error = FCGX_GetError(fcgiRequest_.out); if (error > 0) { char buffer[256]; str << "Cannot write data to fastcgi socket: " << strerror_r(error, buffer, sizeof(buffer)) << ". "; } else { str << "FastCGI error. "; } generateRequestInfo(request_.get(), str); throw std::runtime_error(str.str()); } return num; }
/* *---------------------------------------------------------------------- * * 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); }
/* *---------------------------------------------------------------------- * * ProcessManagementRecord -- * * Reads and responds to a management record. The only type of * management record this library understands is FCGI_GET_VALUES. * The only variables that this library's FCGI_GET_VALUES * understands are FCGI_MAX_CONNS, FCGI_MAX_REQS, and FCGI_MPXS_CONNS. * Ignore other FCGI_GET_VALUES variables; respond to other * management records with a FCGI_UNKNOWN_TYPE record. * *---------------------------------------------------------------------- */ static int ProcessManagementRecord(int type, FCGX_Stream * stream) { FCGX_Stream_Data *data = (FCGX_Stream_Data *) stream->data; ParamsPtr paramsPtr = NewParams(3); char **pPtr; char response[64]; /* 64 = 8 + 3*(1+1+14+1)* + padding */ char *responseP = &response[FCGI_HEADER_LEN]; char *name, value = '\0'; int len, paddedLen; if (type == FCGI_GET_VALUES) { ReadParams(paramsPtr, stream); if ((FCGX_GetError(stream) != 0) || (data->contentLen != 0)) { FreeParams(¶msPtr); return FCGX_PROTOCOL_ERROR; } for (pPtr = paramsPtr->vec; pPtr < paramsPtr->cur; pPtr++) { name = *pPtr; *(strchr(name, '=')) = '\0'; if (strcmp(name, FCGI_MAX_CONNS) == 0) { value = '1'; } else if (strcmp(name, FCGI_MAX_REQS) == 0) { value = '1'; } else if (strcmp(name, FCGI_MPXS_CONNS) == 0) { value = '0'; } else { name = NULL; } if (name != NULL) { #include <fmt.h> len = strlen(name); responseP[0] = (char)len; responseP[1] = (char)1; fmt_str(responseP + 2, name); responseP[2 + len] = value; responseP[3 + len] = '\0'; // sprintf(responseP, "%c%c%s%c", len, 1, name, value); responseP += len + 3; } } len = responseP - &response[FCGI_HEADER_LEN]; paddedLen = AlignInt8(len); *((FCGI_Header *) response) = MakeHeader(FCGI_GET_VALUES_RESULT, FCGI_NULL_REQUEST_ID, len, paddedLen - len); FreeParams(¶msPtr); } else { paddedLen = len = sizeof(FCGI_UnknownTypeBody); ((FCGI_UnknownTypeRecord *) response)->header = MakeHeader(FCGI_UNKNOWN_TYPE, FCGI_NULL_REQUEST_ID, len, 0); ((FCGI_UnknownTypeRecord *) response)->body = MakeUnknownTypeBody(type); } if (write_it_all(data->reqDataPtr->ipcFd, response, FCGI_HEADER_LEN + paddedLen) < 0) { SetError(stream, OS_Errno); return -1; } return MGMT_RECORD; }
int main(int argc, char **argv, char **envp) { int count; FCGX_Stream *paramsStream; fd_set readFdSet, writeFdSet; int numFDs, selectStatus; unsigned char headerBuff[8]; int headerLen, valueLen; char *equalPtr; FCGI_BeginRequestRecord beginRecord; int doBind, doStart, nServers; char appPath[MAXPATHLEN], bindPath[MAXPATHLEN]; if(ParseArgs(argc, argv, &doBind, &doStart, (char *) &bindPath, (char *) &appPath, &nServers)) { fprintf(stderr, "Usage:\n" " cgi-fcgi -f <cmdPath> , or\n" " cgi-fcgi -connect <connName> <appPath> [<nServers>] , or\n" " cgi-fcgi -start -connect <connName> <appPath> [<nServers>] , or\n" " cgi-fcgi -bind -connect <connName> ,\n" "where <connName> is either the pathname of a UNIX domain socket\n" "or (if -bind is given) a hostName:portNumber specification\n" "or (if -start is given) a :portNumber specification (uses local host).\n"); exit(1); } if(doBind) { appServerSock = OS_FcgiConnect(bindPath); } if(doStart && (!doBind || appServerSock < 0)) { FCGI_Start(bindPath, appPath, nServers); if(!doBind) { exit(0); } else { appServerSock = OS_FcgiConnect(bindPath); } } if(appServerSock < 0) { fprintf(stderr, "Could not connect to %s\n", bindPath); exit(errno); } /* * Set an arbitrary non-null FCGI RequestId */ requestId = 1; /* * XXX: Send FCGI_GET_VALUES */ /* * XXX: Receive FCGI_GET_VALUES_RESULT */ /* * Send FCGI_BEGIN_REQUEST (XXX: hack, separate write) */ beginRecord.header = MakeHeader(FCGI_BEGIN_REQUEST, requestId, sizeof(beginRecord.body), 0); beginRecord.body = MakeBeginRequestBody(FCGI_RESPONDER, TRUE); count = write(appServerSock, &beginRecord, sizeof(beginRecord)); if(count != sizeof(beginRecord)) { exit(errno); } /* * Send environment to the FCGI application server */ paramsStream = CreateWriter(appServerSock, requestId, 8192, FCGI_PARAMS); for( ; *envp != NULL; envp++) { equalPtr = strchr(*envp, '='); if(equalPtr == NULL) { exit(1000); } valueLen = strlen(equalPtr + 1); FCGIUtil_BuildNameValueHeader( equalPtr - *envp, valueLen, &headerBuff[0], &headerLen); if(FCGX_PutStr((char *) &headerBuff[0], headerLen, paramsStream) < 0 || FCGX_PutStr(*envp, equalPtr - *envp, paramsStream) < 0 || FCGX_PutStr(equalPtr + 1, valueLen, paramsStream) < 0) { exit(FCGX_GetError(paramsStream)); } } FCGX_FClose(paramsStream); FreeStream(¶msStream); /* * Perform the event loop until AppServerReadHander sees FCGI_END_REQUEST */ fromWS.stop = fromWS.next = &fromWS.buff[0]; webServerReadHandlerEOF = FALSE; FD_ZERO(&readFdSet); FD_ZERO(&writeFdSet); numFDs = max(appServerSock, STDIN_FILENO) + 1; SetFlags(appServerSock, O_NONBLOCK); for(;;) { if((fromWS.stop == fromWS.next) && !webServerReadHandlerEOF) { FD_SET(STDIN_FILENO, &readFdSet); } else { FD_CLR(STDIN_FILENO, &readFdSet); } if(fromWS.stop != fromWS.next) { FD_SET(appServerSock, &writeFdSet); } else { FD_CLR(appServerSock, &writeFdSet); } FD_SET(appServerSock, &readFdSet); selectStatus = select(numFDs, &readFdSet, &writeFdSet, NULL, NULL); if(selectStatus < 0) { exit(errno); } if(selectStatus == 0) { /* * Should not happen, no select timeout. */ continue; } if(FD_ISSET(STDIN_FILENO, &readFdSet)) { WebServerReadHandler(); } if(FD_ISSET(appServerSock, &writeFdSet)) { AppServerWriteHandler(); } if(FD_ISSET(appServerSock, &readFdSet)) { AppServerReadHandler(); } if(exitStatusSet) { exit(exitStatus); } } }