/* 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; }
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; }