Ejemplo n.º 1
0
/*
 *  Split a packet if required so it fits in the downstream queue. Put back the 2nd portion of the split packet on the queue.
 *  Ensure that the packet is not larger than "size" if it is greater than zero.
 */
int maResizePacket(MaQueue *q, MaPacket *packet, int size)
{
    MaPacket    *tail;
    MaConn      *conn;
    MprCtx      ctx;
    int         len;
    
    conn = q->conn;
    if (size <= 0) {
        size = MAXINT;
    }
    ctx = conn->request ? (MprCtx) conn->request : (MprCtx) conn;

    if (packet->esize > size) {
        if ((tail = maSplitPacket(ctx, packet, size)) == 0) {
            return MPR_ERR_NO_MEMORY;
        }
    } else {
        /*
         *  Calculate the size that will fit
         */
        len = packet->content ? maGetPacketLength(packet) : 0;
        size = min(size, len);
        size = min(size, q->nextQ->max);
        size = min(size, q->nextQ->packetSize);
        if (size == 0 || size == len) {
            return 0;
        }
        if ((tail = maSplitPacket(ctx, packet, size)) == 0) {
            return MPR_ERR_NO_MEMORY;
        }
    }
    maPutBack(q, tail);
    return 0;
}
Ejemplo n.º 2
0
/*
 *  Apply chunks to dynamic outgoing data. 
 */
static void outgoingChunkService(MaQueue *q)
{
    MaConn      *conn;
    MaPacket    *packet;
    MaResponse  *resp;

    conn = q->conn;
    resp = conn->response;

    if (!(q->flags & MA_QUEUE_SERVICED)) {
        /*
         *  If the last packet is the end packet, we have all the data. Thus we know the actual content length 
         *  and can bypass the chunk handler.
         */
        if (q->last->flags & MA_PACKET_END) {
            if (resp->chunkSize < 0 && resp->length <= 0) {
                /*  
                 *  Set the response content length and thus disable chunking -- not needed as we know the entity length.
                 */
                resp->length = q->count;
            }
        } else {
            if (resp->chunkSize < 0 && resp->entityLength < 0) {
                resp->chunkSize = (int) min(conn->http->limits.maxChunkSize, q->max);
            }
        }
    }

    if (resp->chunkSize <= 0) {
        maDefaultOutgoingServiceStage(q);
    } else {
        for (packet = maGet(q); packet; packet = maGet(q)) {
            if (!(packet->flags & MA_PACKET_HEADER)) {
                if (maGetPacketLength(packet) > resp->chunkSize) {
                    maResizePacket(q, packet, resp->chunkSize);
                }
            }
            if (!maWillNextQueueAccept(q, packet)) {
                maPutBack(q, packet);
                return;
            }
            if (!(packet->flags & MA_PACKET_HEADER)) {
                setChunkPrefix(q, packet);
            }
            maPutNext(q, packet);
        }
    }
}
Ejemplo n.º 3
0
static void writeToCGI(MaQueue *q)
{
    MaConn      *conn;
    MaPacket    *packet;
    MprCmd      *cmd;
    MprBuf      *buf;
    int         len, rc, err;

    cmd = (MprCmd*) q->pair->queueData;
    mprAssert(cmd);
    conn = q->conn;

    for (packet = maGet(q); packet && !conn->requestFailed; packet = maGet(q)) {
        buf = packet->content;
        len = mprGetBufLength(buf);
        mprAssert(len > 0);
        rc = mprWriteCmdPipe(cmd, MPR_CMD_STDIN, mprGetBufStart(buf), len);
        mprLog(q, 5, "CGI: write %d bytes to gateway. Rc rc %d, errno %d", len, rc, mprGetOsError());
        if (rc < 0) {
            err = mprGetError();
            if (err == EINTR) {
                continue;
            } else if (err == EAGAIN || err == EWOULDBLOCK) {
                break;
            }
            mprLog(q, 2, "CGI: write to gateway failed for %d bytes, rc %d, errno %d", len, rc, mprGetOsError());
            mprCloseCmdFd(cmd, MPR_CMD_STDIN);
            maFailRequest(conn, MPR_HTTP_CODE_BAD_GATEWAY, "Can't write body data to CGI gateway");
            break;

        } else {
            mprLog(q, 5, "CGI: write to gateway %d bytes asked to write %d", rc, len);
            mprAdjustBufStart(buf, rc);
            if (mprGetBufLength(buf) > 0) {
                maPutBack(q, packet);
            } else {
                maFreePacket(q, packet);
            }
        }
    }
}