static void incomingEjs(HttpQueue *q, HttpPacket *packet) { HttpConn *conn; HttpRx *rx; conn = q->conn; rx = conn->rx; if (httpGetPacketLength(packet) == 0) { if (rx->remainingContent > 0) { httpError(conn, HTTP_CODE_BAD_REQUEST, "Client supplied insufficient body data"); } httpPutForService(q, packet, 0); } else { httpJoinPacketForService(q, packet, 0); } HTTP_NOTIFY(q->conn, HTTP_EVENT_READABLE, 0); }
/* Incoming data routine. Simply transfer the data upstream to the next filter or handler. */ static void incoming(HttpQueue *q, HttpPacket *packet) { assert(q); assert(packet); if (q->nextQ->put) { httpPutPacketToNext(q, packet); } else { /* This queue is the last queue in the pipeline */ if (httpGetPacketLength(packet) > 0) { if (packet->flags & HTTP_PACKET_SOLO) { httpPutForService(q, packet, HTTP_DELAY_SERVICE); } else { httpJoinPacketForService(q, packet, 0); } } else { /* Zero length packet means eof */ httpPutForService(q, packet, HTTP_DELAY_SERVICE); } HTTP_NOTIFY(q->conn, HTTP_EVENT_READABLE, 0); } }
/* Incoming data acceptance routine. The service queue is used, but not a service routine as the data is processed immediately. Partial data is buffered on the service queue until a correct mime boundary is seen. */ static void incomingUpload(HttpQueue *q, HttpPacket *packet) { HttpConn *conn; HttpRx *rx; MprBuf *content; Upload *up; char *line, *nextTok; ssize count; int done, rc; assert(packet); conn = q->conn; rx = conn->rx; up = q->queueData; if (conn->error) { return; } if (httpGetPacketLength(packet) == 0) { if (up->contentState != HTTP_UPLOAD_CONTENT_END) { httpError(conn, HTTP_CODE_BAD_REQUEST, "Client supplied insufficient upload data"); } httpPutPacketToNext(q, packet); return; } /* Put the packet data onto the service queue for buffering. This aggregates input data incase we don't have a complete mime record yet. */ httpJoinPacketForService(q, packet, 0); packet = q->first; content = packet->content; count = httpGetPacketLength(packet); for (done = 0, line = 0; !done; ) { if (up->contentState == HTTP_UPLOAD_BOUNDARY || up->contentState == HTTP_UPLOAD_CONTENT_HEADER) { /* Parse the next input line */ line = mprGetBufStart(content); if ((nextTok = memchr(line, '\n', mprGetBufLength(content))) == 0) { /* Incomplete line */ break; } *nextTok++ = '\0'; mprAdjustBufStart(content, (int) (nextTok - line)); line = strim(line, "\r", MPR_TRIM_END); } switch (up->contentState) { case HTTP_UPLOAD_BOUNDARY: if (processUploadBoundary(q, line) < 0) { done++; } break; case HTTP_UPLOAD_CONTENT_HEADER: if (processUploadHeader(q, line) < 0) { done++; } break; case HTTP_UPLOAD_CONTENT_DATA: rc = processUploadData(q); if (rc < 0) { done++; } if (httpGetPacketLength(packet) < up->boundaryLen) { /* Incomplete boundary - return to get more data */ done++; } break; case HTTP_UPLOAD_CONTENT_END: done++; break; } } q->count -= (count - httpGetPacketLength(packet)); assert(q->count >= 0); if (httpGetPacketLength(packet) == 0) { /* Quicker to remove the buffer so the packets don't have to be joined the next time */ httpGetPacket(q); } else { /* Compact the buffer to prevent memory growth. There is often residual data after the boundary for the next block. */ if (packet != rx->headerPacket) { mprCompactBuf(content); } } }