static void processDataFromClient(TConn * const connectionP, abyss_bool const lastReqOnConn, abyss_bool * const keepAliveP) { TSession session; RequestInit(&session, connectionP); session.serverDeniesKeepalive = lastReqOnConn; RequestRead(&session); if (session.status == 0) { if (session.version.major >= 2) ResponseStatus(&session, 505); else if (!RequestValidURI(&session)) ResponseStatus(&session, 400); else runUserHandler(&session, connectionP->server->srvP); } assert(session.status != 0); if (session.responseStarted) HTTPWriteEndChunk(&session); else ResponseError(&session); *keepAliveP = HTTPKeepalive(&session); SessionLog(&session); RequestFree(&session); }
static void handleDirectory(TSession *const sessionP, const char *const dirName, time_t const fileModTime, MIMEType *const mimeTypeP) { bool text; bool ascending; uint16_t sort; /* 1=by name, 2=by date */ const char *error; determineSortType(sessionP->requestInfo.query, &ascending, &sort, &text, &error); if (error) { ResponseStatus(sessionP, 400); xmlrpc_strfree(error); } else if (notRecentlyModified(sessionP, fileModTime)) { ResponseStatus(sessionP, 304); ResponseWriteStart(sessionP); } else { TPool pool; bool succeeded; succeeded = PoolCreate(&pool, 1024); if (!succeeded) ResponseStatus(sessionP, 500); else { TList list; uint16_t responseStatus; const char *error; generateListing(&list, dirName, sessionP->requestInfo.uri, &pool, &error, &responseStatus); if (error) { ResponseStatus(sessionP, responseStatus); xmlrpc_strfree(error); } else { ResponseStatus(sessionP, 200); ResponseContentType(sessionP, text ? "text/plain" : "text/html"); addLastModifiedHeader(sessionP, fileModTime); ResponseChunked(sessionP); ResponseWriteStart(sessionP); if (sessionP->requestInfo.method != m_head) sendDirectoryDocument(&list, ascending, sort, text, sessionP->requestInfo.uri, mimeTypeP, sessionP); HTTPWriteEndChunk(sessionP); ListFree(&list); } PoolFree(&pool); } } }
static void processRequestFromClient(TConn * const connectionP, bool const lastReqOnConn, uint32_t const timeout, bool * const keepAliveP) { /*---------------------------------------------------------------------------- Get and execute one HTTP request from client connection *connectionP, through the connection buffer. I.e. Some of the request may already be in the connection buffer, and we may leave some of later requests in the connection buffer. In fact, due to timing considerations, we assume the client has begun sending the request, which as a practical matter means Caller has already deposited some of it in the connection buffer. If there isn't one full request in the buffer now, we wait for one full request to come through the buffer, up to 'timeout'. We return as *keepAliveP whether Caller should keep the connection alive for a while for possible future requests from the client, based on 'lastReqOnConn' and the content of the HTTP request. Executing the request consists primarily of calling the URI handlers that are associated with the connection (*connectionP), passing each the request information we read. Each handler can respond according to the HTTP method (GET, POST, etc) and URL etc, and that response may be either to execute the request and send the response or refuse the request and let us call the next one in the list. -----------------------------------------------------------------------------*/ TSession session; const char * error; uint16_t httpErrorCode; RequestInit(&session, connectionP); session.serverDeniesKeepalive = lastReqOnConn; RequestRead(&session, timeout, &error, &httpErrorCode); if (error) { ResponseStatus(&session, httpErrorCode); ResponseError2(&session, error); xmlrpc_strfree(error); } else { if (session.version.major >= 2) handleReqTooNewHttpVersion(&session); else if (!RequestValidURI(&session)) handleReqInvalidURI(&session); else runUserHandler(&session, connectionP->server->srvP); } assert(session.status != 0); if (session.responseStarted) HTTPWriteEndChunk(&session); else ResponseError(&session); *keepAliveP = HTTPKeepalive(&session); SessionLog(&session); RequestFree(&session); }
static abyss_bool ServerDirectoryHandler(TSession * const r, char * const z, time_t const fileModTime, MIMEType * const mimeTypeP) { TList list; abyss_bool text; abyss_bool ascending; uint16_t sort; /* 1=by name, 2=by date */ TPool pool; TDate date; const char * error; uint16_t responseStatus; TDate dirdate; const char * imsHdr; determineSortType(r->request_info.query, &ascending, &sort, &text, &error); if (error) { ResponseStatus(r,400); xmlrpc_strfree(error); return TRUE; } fileDate(r, fileModTime, &dirdate); imsHdr = RequestHeaderValue(r, "If-Modified-Since"); if (imsHdr) { if (DateDecode(imsHdr, &date)) { if (DateCompare(&dirdate, &date) <= 0) { ResponseStatus(r, 304); ResponseWrite(r); return TRUE; } } } if (!PoolCreate(&pool, 1024)) { ResponseStatus(r, 500); return TRUE; } generateListing(&list, z, r->request_info.uri, &pool, &error, &responseStatus); if (error) { ResponseStatus(r, responseStatus); xmlrpc_strfree(error); PoolFree(&pool); return TRUE; } /* Send something to the user to show that we are still alive */ ResponseStatus(r, 200); ResponseContentType(r, (text ? "text/plain" : "text/html")); if (DateToString(&dirdate, z)) ResponseAddField(r, "Last-Modified", z); ResponseChunked(r); ResponseWrite(r); if (r->request_info.method!=m_head) sendDirectoryDocument(&list, ascending, sort, text, r->request_info.uri, mimeTypeP, r, z); HTTPWriteEndChunk(r); /* Free memory and exit */ ListFree(&list); PoolFree(&pool); return TRUE; }
abyss_bool ResponseWriteEnd(TSession * const sessionP) { return HTTPWriteEndChunk(sessionP); }