示例#1
0
/*  
    Prepare a data packet for sending downstream. This involves reading file data into a suitably sized packet. Return
    the 1 if the packet was sent entirely, return zero if the packet could not be completely sent. Return a negative
    error code for write errors. This may split the packet if it exceeds the downstreams maximum packet size.
 */
static int prepPacket(HttpQueue *q, HttpPacket *packet)
{
    HttpQueue   *nextQ;
    ssize       size, nbytes;	
    nextQ = q->nextQ;
    if (packet->esize > nextQ->packetSize) {
        httpPutBackPacket(q, httpSplitPacket(packet, nextQ->packetSize));
        size = nextQ->packetSize;
    } else {
        size = (ssize) packet->esize;
    }
    if ((size + nextQ->count) > nextQ->max) {
        /*  
            The downstream queue is full, so disable the queue and service downstream queue.
            Will re-enable via a writable event on the connection.
         */
        httpSuspendQueue(q);
        if (!(nextQ->flags & HTTP_QUEUE_SUSPENDED)) {
            httpScheduleQueue(nextQ);
        }
        return 0;
    }
    if ((nbytes = readFileData(q, packet, q->ioPos, size)) != size) {
        return MPR_ERR_CANT_READ;
    }
    q->ioPos += nbytes;
    return 1;
}
示例#2
0
static HttpPacket *selectBytes(HttpQueue *q, HttpPacket *packet)
{
    HttpRange   *range;
    HttpStream  *stream;
    HttpTx      *tx;
    MprOff      endPacket, length, gap, span;
    ssize       count;

    stream = q->stream;
    tx = stream->tx;

    if ((range = tx->currentRange) == 0) {
        return 0;
    }

    /*
        Process the data packet over multiple ranges ranges until all the data is processed or discarded.
     */
    while (range && packet) {
        length = httpGetPacketLength(packet);
        if (length <= 0) {
            return 0;
        }
        endPacket = tx->rangePos + length;
        if (endPacket < range->start) {
            /* Packet is before the next range, so discard the entire packet and seek forwards */
            tx->rangePos += length;
            return 0;

        } else if (tx->rangePos < range->start) {
            /*  Packet starts before range so skip some data, but some packet data is in range */
            gap = (range->start - tx->rangePos);
            tx->rangePos += gap;
            if (gap < length) {
                httpAdjustPacketStart(packet, (ssize) gap);
            }
            if (tx->rangePos >= range->end) {
                range = tx->currentRange = range->next;
            }
            /* Keep going and examine next range */

        } else {
            /* In range */
            assert(range->start <= tx->rangePos && tx->rangePos < range->end);
            span = min(length, (range->end - tx->rangePos));
            span = max(span, 0);
            count = (ssize) min(span, q->nextQ->packetSize);
            assert(count > 0);
            if (length > count) {
                /* Split packet if packet extends past range */
                httpPutBackPacket(q, httpSplitPacket(packet, count));
            }
            if (tx->rangeBoundary) {
                httpPutPacketToNext(q, createRangePacket(stream, range));
            }
            tx->rangePos += count;
            if (tx->rangePos >= range->end) {
                tx->currentRange = range->next;
            }
            break;
        }
    }
    return packet;
}