/* * Return true if the next queue will accept this packet. If not, then disable the queue's service procedure. * This may split the packet if it exceeds the downstreams maximum packet size. */ bool maWillNextQueueAccept(MaQueue *q, MaPacket *packet) { MaQueue *next; int64 size; next = q->nextQ; size = maGetPacketLength(packet); if (size <= next->packetSize && (size + next->count) <= next->max) { return 1; } if (maResizePacket(q, packet, 0) < 0) { return 0; } size = maGetPacketLength(packet); if (size <= next->packetSize && (size + next->count) <= next->max) { return 1; } /* * The downstream queue is full, so disable the queue and mark the downstream queue as full and service immediately. */ maDisableQueue(q); next->flags |= MA_QUEUE_FULL; maScheduleQueue(next); return 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); } } }