/* * Complete the request and return true if there is a pipelined request following. */ bool maProcessCompletion(MaConn *conn) { MaRequest *req; MaPacket *packet; bool more; mprAssert(conn->state == MPR_HTTP_STATE_COMPLETE); req = conn->request; maLogRequest(conn); #if BLD_DEBUG mprLog(req, 4, "Request complete used %,d K, conn usage %,d K, mpr usage %,d K, page usage %,d K", req->arena->allocBytes / 1024, conn->arena->allocBytes / 1024, mprGetMpr(conn)->heap.allocBytes / 1024, mprGetMpr(conn)->pageHeap.allocBytes / 1024); /* mprPrintAllocReport(mprGetMpr(conn), "Before completing request"); */ #endif packet = conn->input; more = packet && (mprGetBufLength(packet->content) > 0); if (mprGetParent(packet) != conn) { if (more) { conn->input = maSplitPacket(conn, packet, 0); mprAssert(mprGetParent(conn->input) == conn); } else { conn->input = 0; } } /* * This will free the request, response, pipeline and call maPrepConnection to reset the state. */ mprFree(req->arena); return (conn->disconnected || conn->connectionFailed) ? 0 : more; }
int destroyRequest(MaRequest *req) { MaConn *conn; conn = req->conn; maPrepConnection(conn); if (conn->input) { /* Left over packet */ if (mprGetParent(conn->input) != conn) { conn->input = maSplitPacket(conn, conn->input, 0); } } #if BLD_DEBUG { MprTime elapsed = mprGetTime(req) - req->startTime; #if MPR_HIGH_RES_TIMER if (elapsed < 1000) { mprLog(conn, 4, "TIME: Request %s took %,d msec %,d ticks", req->url, elapsed, mprGetTicks() - req->startTicks); } else #endif mprLog(conn, 4, "TIME: Request %s took %,d msec", req->url, elapsed); } #endif return 0; }
void maSetAuthRealm(MaAuth *auth, cchar *realm) { if (mprGetParent(auth->requiredRealm) == auth) { mprFree(auth->requiredRealm); } auth->requiredRealm = mprStrdup(auth, realm); }
/* * Get the next input token. The content buffer is advanced to the next token. This routine always returns a * non-zero token. The empty string means the delimiter was not found. */ static char *getToken(MaConn *conn, cchar *delim) { MprBuf *buf; char *token, *nextToken; int len; mprAssert(mprGetParent(conn->input) == conn); buf = conn->input->content; len = mprGetBufLength(buf); if (len == 0) { return ""; } token = mprGetBufStart(buf); nextToken = mprStrnstr(mprGetBufStart(buf), delim, len); if (nextToken) { *nextToken = '\0'; len = (int) strlen(delim); nextToken += len; buf->start = nextToken; } else { buf->start = mprGetBufEnd(buf); mprAddNullToBuf(buf); } return token; }
int maAddLocation(MaHost *host, MaLocation *newLocation) { MaLocation *location; int next, rc; mprAssert(newLocation); mprAssert(newLocation->prefix); if (mprGetParent(host->locations) == host->parent) { host->locations = mprDupList(host, host->parent->locations); } /* * Sort in reverse collating sequence. Must make sure that /abc/def sorts before /abc */ for (next = 0; (location = mprGetNextItem(host->locations, &next)) != 0; ) { rc = strcmp(newLocation->prefix, location->prefix); if (rc == 0) { mprRemoveItem(host->locations, location); mprInsertItemAtPos(host->locations, next - 1, newLocation); return 0; } if (strcmp(newLocation->prefix, location->prefix) > 0) { mprInsertItemAtPos(host->locations, next - 1, newLocation); return 0; } } mprAddItem(host->locations, newLocation); return 0; }
int maInsertDir(MaHost *host, MaDir *newDir) { MaDir *dir; int rc, next; mprAssert(newDir); mprAssert(newDir->path); if (mprGetParent(host->dirs) == host->parent) { host->dirs = mprDupList(host, host->parent->dirs); } /* * Sort in reverse collating sequence. Must make sure that /abc/def sorts before /abc */ for (next = 0; (dir = mprGetNextItem(host->dirs, &next)) != 0; ) { mprAssert(dir->path); rc = strcmp(newDir->path, dir->path); if (rc == 0) { mprRemoveItem(host->dirs, dir); mprInsertItemAtPos(host->dirs, next, newDir); return 0; } else if (rc > 0) { mprInsertItemAtPos(host->dirs, next - 1, newDir); return 0; } } mprAddItem(host->dirs, newDir); return 0; }
int maInsertAlias(MaHost *host, MaAlias *newAlias) { MaAlias *alias, *old; int rc, next, index; if (mprGetParent(host->aliases) == host->parent) { host->aliases = mprDupList(host, host->parent->aliases); } /* * Sort in reverse collating sequence. Must make sure that /abc/def sorts before /abc. But we sort redirects with * status codes first. */ for (next = 0; (alias = mprGetNextItem(host->aliases, &next)) != 0; ) { rc = strcmp(newAlias->prefix, alias->prefix); if (rc == 0) { index = mprLookupItem(host->aliases, alias); old = (MaAlias*) mprGetItem(host->aliases, index); mprRemoveItem(host->aliases, alias); mprInsertItemAtPos(host->aliases, next - 1, newAlias); return 0; } else if (rc > 0) { if (newAlias->redirectCode >= alias->redirectCode) { mprInsertItemAtPos(host->aliases, next - 1, newAlias); return 0; } } } mprAddItem(host->aliases, newAlias); return 0; }
void maSetAuthRequiredUsers(MaAuth *auth, cchar *users) { if (mprGetParent(auth->requiredUsers) == auth) { mprFree(auth->requiredUsers); } auth->requiredUsers = mprStrdup(auth, users); auth->flags |= MA_AUTH_REQUIRED; auth->anyValidUser = 0; }
void maSetAuthQop(MaAuth *auth, cchar *qop) { if (mprGetParent(auth->qop) == auth) { mprFree(auth->qop); } if (strcmp(qop, "auth") == 0 || strcmp(qop, "auth-int") == 0) { auth->qop = mprStrdup(auth, qop); } else { auth->qop = mprStrdup(auth, ""); } }
int ejsAddItemToSharedList(MprCtx ctx, EjsList *lp, cvoid *item) { EjsList tmp; if (lp->items == NULL || mprGetParent(lp->items) != ctx) { tmp = *lp; lp->items = 0; lp->length = 0; if (ejsCopyList(ctx, lp, &tmp) < 0) { return MPR_ERR_NO_MEMORY; } } return ejsAddItem(ctx, lp, item); }
/* * Process request body data (typically post or put content). Packet will be null if the client closed the * connection to signify end of data. */ static bool processContent(MaConn *conn, MaPacket *packet) { MaRequest *req; MaResponse *resp; MaQueue *q; MaHost *host; MprBuf *content; int64 remaining; int nbytes; req = conn->request; resp = conn->response; host = conn->host; q = &resp->queue[MA_QUEUE_RECEIVE]; mprAssert(packet); if (packet == 0) { return 0; } if (conn->connectionFailed) { conn->state = MPR_HTTP_STATE_PROCESSING; maPutForService(resp->queue[MA_QUEUE_SEND].nextQ, maCreateHeaderPacket(resp), 1); return 1; } content = packet->content; if (req->flags & MA_REQ_CHUNKED) { if ((remaining = getChunkPacketSize(conn, content)) == 0) { /* Need more data or bad chunk specification */ if (mprGetBufLength(content) > 0) { conn->input = packet; } return 0; } } else { remaining = req->remainingContent; } nbytes = (int) min(remaining, mprGetBufLength(content)); mprAssert(nbytes >= 0); mprLog(conn, 7, "processContent: packet of %d bytes, remaining %Ld", mprGetBufLength(content), remaining); if (maShouldTrace(conn, MA_TRACE_REQUEST | MA_TRACE_BODY)) { maTraceContent(conn, packet, 0, 0, MA_TRACE_REQUEST | MA_TRACE_BODY); } if (nbytes > 0) { mprAssert(maGetPacketLength(packet) > 0); remaining -= nbytes; req->remainingContent -= nbytes; req->receivedContent += nbytes; if (req->receivedContent >= host->limits->maxBody) { conn->keepAliveCount = 0; maFailConnection(conn, MPR_HTTP_CODE_REQUEST_TOO_LARGE, "Request content body is too big %Ld vs limit %Ld", req->receivedContent, host->limits->maxBody); return 1; } if (packet == req->headerPacket) { /* Preserve headers if more data to come. Otherwise handlers may free the packet and destory the headers */ packet = maSplitPacket(resp, packet, 0); } else { mprStealBlock(resp, packet); } conn->input = 0; if (remaining == 0 && mprGetBufLength(packet->content) > nbytes) { /* * Split excess data belonging to the next pipelined request. */ mprLog(conn, 7, "processContent: Split packet of %d at %d", maGetPacketLength(packet), nbytes); conn->input = maSplitPacket(conn, packet, nbytes); mprAssert(mprGetParent(conn->input) == conn); } if ((q->count + maGetPacketLength(packet)) > q->max) { conn->keepAliveCount = 0; maFailConnection(q->conn, MPR_HTTP_CODE_REQUEST_TOO_LARGE, "Too much body data"); return 1; } maPutNext(q, packet); } else { conn->input = 0; mprStealBlock(resp, packet); } if (req->remainingContent == 0 || conn->requestFailed) { /* * End of input. Send a zero packet EOF signal and enable the handler send queue. */ if (req->remainingContent > 0 && conn->protocol > 0 && !conn->requestFailed) { maFailConnection(conn, MPR_HTTP_CODE_COMMS_ERROR, "Insufficient content data sent with request"); } else { maPutNext(q, maCreateEndPacket(resp)); conn->state = MPR_HTTP_STATE_PROCESSING; maRunPipeline(conn); } return 1; } maServiceQueues(conn); return conn->input ? mprGetBufLength(conn->input->content) : 0; }