Exemple #1
0
/*
 *  Create a new connection object.
 */
static MaConn *createConn(MprCtx ctx, MaHost *host, MprSocket *sock, cchar *ipAddr, int port, MaHostAddress *address)
{
    MaConn      *conn;

    conn = mprAllocObjWithDestructorZeroed(ctx, MaConn, connectionDestructor);
    if (conn == 0) {
        return 0;
    }
    if (host->keepAlive) {
        conn->keepAliveCount = host->maxKeepAlive;
    }
    conn->http = host->server->http;
    conn->sock = sock;
    mprStealBlock(conn, sock);

    conn->state = MPR_HTTP_STATE_BEGIN;
    conn->timeout = host->timeout;
    conn->remotePort = port;
    conn->remoteIpAddr = mprStrdup(conn, ipAddr);
    conn->address = address;
    conn->host = host;
    conn->originalHost = host;
    conn->expire = mprGetTime(conn) + host->timeout;
    conn->eventMask = -1;

    maInitSchedulerQueue(&conn->serviceq);

#if BLD_FEATURE_MULTITHREAD
    conn->mutex = mprCreateLock(conn);
#endif
    return conn;
}
Exemple #2
0
char *mprStealBuf(MprCtx ctx, MprBuf *bp)
{
    char    *str;

    str = (char*) bp->start;

    mprStealBlock(ctx, bp->start);
    bp->start = bp->end = bp->data = bp->endbuf = 0;
    bp->buflen = 0;
    return str;
}
Exemple #3
0
/*
 *  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;
}