static int blockingFileCopy(HttpConn *conn, cchar *path) { MprFile *file; char buf[ME_MAX_BUFFER]; ssize bytes, nbytes, offset; file = mprOpenFile(path, O_RDONLY | O_BINARY, 0); if (file == 0) { mprLog("error http client", 0, "Cannot open %s", path); return MPR_ERR_CANT_OPEN; } mprAddRoot(file); while ((bytes = mprReadFile(file, buf, sizeof(buf))) > 0) { offset = 0; while (bytes > 0) { if ((nbytes = httpWriteBlock(conn->writeq, &buf[offset], bytes, HTTP_BLOCK)) < 0) { mprCloseFile(file); mprRemoveRoot(file); return MPR_ERR_CANT_WRITE; } bytes -= nbytes; offset += nbytes; assert(bytes >= 0); } } httpFlushQueue(conn->writeq, HTTP_BLOCK); mprCloseFile(file); mprRemoveRoot(file); return 0; }
static int blockingFileCopy(HttpConn *conn, cchar *path) { MprFile *file; char buf[MPR_BUFSIZE]; ssize bytes, nbytes, offset; int oldMode; file = mprOpenFile(path, O_RDONLY | O_BINARY, 0); if (file == 0) { mprError("Can't open %s", path); return MPR_ERR_CANT_OPEN; } mprAddRoot(file); oldMode = mprSetSocketBlockingMode(conn->sock, 1); while ((bytes = mprReadFile(file, buf, sizeof(buf))) > 0) { offset = 0; while (bytes > 0) { if ((nbytes = httpWriteBlock(conn->writeq, &buf[offset], bytes)) < 0) { mprCloseFile(file); mprRemoveRoot(file); return MPR_ERR_CANT_WRITE; } bytes -= nbytes; offset += nbytes; mprAssert(bytes >= 0); } mprYield(0); } httpFlushQueue(conn->writeq, 1); mprSetSocketBlockingMode(conn->sock, oldMode); mprCloseFile(file); mprRemoveRoot(file); return 0; }
static ssize writeBody(HttpConn *conn, MprList *files) { MprFile *file; char buf[HTTP_BUFSIZE], *path, *pair; ssize bytes, len, count, nbytes, sofar; int next, oldMode; if (app->upload) { if (httpWriteUploadData(conn, app->files, app->formData) < 0) { mprError("Can't write upload data %s", httpGetError(conn)); return MPR_ERR_CANT_WRITE; } } else { if (app->formData) { count = mprGetListLength(app->formData); for (next = 0; (pair = mprGetNextItem(app->formData, &next)) != 0; ) { len = strlen(pair); if (next < count) { len = slen(pair); if (httpWrite(conn->writeq, pair, len) != len || httpWrite(conn->writeq, "&", 1) != 1) { return MPR_ERR_CANT_WRITE; } } else { if (httpWrite(conn->writeq, pair, len) != len) { return MPR_ERR_CANT_WRITE; } } } } if (files) { mprAssert(mprGetListLength(files) == 1); for (next = 0; (path = mprGetNextItem(files, &next)) != 0; ) { if (strcmp(path, "-") == 0) { file = mprAttachFileFd(0, "stdin", O_RDONLY | O_BINARY); } else { file = mprOpenFile(path, O_RDONLY | O_BINARY, 0); } if (file == 0) { mprError("Can't open \"%s\"", path); return MPR_ERR_CANT_OPEN; } app->inFile = file; if (app->verbose) { mprPrintf("uploading: %s\n", path); } oldMode = mprSetSocketBlockingMode(conn->sock, 1); while ((bytes = mprReadFile(file, buf, sizeof(buf))) > 0) { sofar = 0; while (bytes > 0) { if ((nbytes = httpWriteBlock(conn->writeq, &buf[sofar], bytes)) < 0) { mprCloseFile(file); return MPR_ERR_CANT_WRITE; } bytes -= nbytes; sofar += nbytes; mprAssert(bytes >= 0); } mprYield(0); } httpFlushQueue(conn->writeq, 1); mprSetSocketBlockingMode(conn->sock, oldMode); mprCloseFile(file); app->inFile = 0; } } if (app->bodyData) { mprAddNullToBuf(app->bodyData); len = mprGetBufLength(app->bodyData); if (httpWriteBlock(conn->writeq, mprGetBufStart(app->bodyData), len) != len) { return MPR_ERR_CANT_WRITE; } } } return 0; }
/* Write a block of data. This is the lowest level write routine for data. This will buffer the data and flush if the queue buffer is full. Flushing is done by calling httpFlushQueue which will service queues as required. This may call the queue outgoing service routine and disable downstream queues if they are overfull. This routine will always accept the data and never return "short". */ PUBLIC ssize httpWriteBlock(HttpQueue *q, cchar *buf, ssize len, int flags) { HttpPacket *packet; HttpConn *conn; HttpTx *tx; ssize totalWritten, packetSize, thisWrite; assert(q == q->conn->writeq); conn = q->conn; tx = conn->tx; if (flags == 0) { flags = HTTP_BUFFER; } if (tx == 0 || tx->finalizedOutput) { return MPR_ERR_CANT_WRITE; } tx->responded = 1; for (totalWritten = 0; len > 0; ) { mprTrace(7, "httpWriteBlock q_count %d, q_max %d", q->count, q->max); if (conn->state >= HTTP_STATE_FINALIZED) { return MPR_ERR_CANT_WRITE; } if (q->last && q->last != q->first && q->last->flags & HTTP_PACKET_DATA && mprGetBufSpace(q->last->content) > 0) { packet = q->last; } else { packetSize = (tx->chunkSize > 0) ? tx->chunkSize : q->packetSize; if ((packet = httpCreateDataPacket(packetSize)) == 0) { return MPR_ERR_MEMORY; } httpPutForService(q, packet, HTTP_DELAY_SERVICE); } assert(mprGetBufSpace(packet->content) > 0); thisWrite = min(len, mprGetBufSpace(packet->content)); if (flags & (HTTP_BLOCK | HTTP_NON_BLOCK)) { thisWrite = min(thisWrite, q->max - q->count); } if (thisWrite > 0) { if ((thisWrite = mprPutBlockToBuf(packet->content, buf, thisWrite)) == 0) { return MPR_ERR_MEMORY; } buf += thisWrite; len -= thisWrite; q->count += thisWrite; totalWritten += thisWrite; } if (q->count >= q->max) { httpFlushQueue(q, 0); if (q->count >= q->max) { if (flags & HTTP_NON_BLOCK) { break; } else if (flags & HTTP_BLOCK) { while (q->count >= q->max && !tx->finalized) { if (!mprWaitForSingleIO((int) conn->sock->fd, MPR_WRITABLE, conn->limits->inactivityTimeout)) { return MPR_ERR_TIMEOUT; } httpResumeQueue(conn->connectorq); httpServiceQueues(conn); } } } } } if (conn->error) { return MPR_ERR_CANT_WRITE; } return totalWritten; }
static ssize writeBody(HttpConn *conn, MprList *files) { MprFile *file; char buf[ME_MAX_BUFFER], *path, *pair; ssize bytes, len, count, nbytes, sofar; int next; if (app->upload) { if (httpWriteUploadData(conn, app->files, app->formData) < 0) { return MPR_ERR_CANT_WRITE; } } else { if (app->formData) { count = mprGetListLength(app->formData); for (next = 0; (pair = mprGetNextItem(app->formData, &next)) != 0; ) { len = strlen(pair); if (next < count) { len = slen(pair); if (httpWriteString(conn->writeq, pair) != len || httpWriteString(conn->writeq, "&") != 1) { return MPR_ERR_CANT_WRITE; } } else { if (httpWrite(conn->writeq, pair, len) != len) { return MPR_ERR_CANT_WRITE; } } } } if (files) { assert(mprGetListLength(files) == 1); for (next = 0; (path = mprGetNextItem(files, &next)) != 0; ) { if (strcmp(path, "-") == 0) { file = mprAttachFileFd(0, "stdin", O_RDONLY | O_BINARY); } else { file = mprOpenFile(path, O_RDONLY | O_BINARY, 0); } if (file == 0) { mprLog("error http", 0, "Cannot open \"%s\"", path); return MPR_ERR_CANT_OPEN; } app->inFile = file; if (app->verbose) { mprPrintf("uploading: %s\n", path); } while ((bytes = mprReadFile(file, buf, sizeof(buf))) > 0) { sofar = 0; while (bytes > 0) { if ((nbytes = httpWriteBlock(conn->writeq, &buf[sofar], bytes, HTTP_BLOCK)) < 0) { mprCloseFile(file); return MPR_ERR_CANT_WRITE; } bytes -= nbytes; sofar += nbytes; assert(bytes >= 0); } } httpFlushQueue(conn->writeq, HTTP_BLOCK); mprCloseFile(file); app->inFile = 0; } } if (app->bodyData) { len = mprGetBufLength(app->bodyData); if (httpWriteBlock(conn->writeq, mprGetBufStart(app->bodyData), len, HTTP_BLOCK) != len) { return MPR_ERR_CANT_WRITE; } } } return 0; }
/* Flush the write queue */ PUBLIC void httpFlush(HttpConn *conn) { httpFlushQueue(conn->writeq, !conn->async); }