/* * Outgoing data service routine. May be called multiple times. */ static void sendOutgoingService(MaQueue *q) { MaConn *conn; MaResponse *resp; int written; int errCode; conn = q->conn; resp = conn->response; if (conn->sock == 0) { return; } /* * Loop doing non-blocking I/O until blocked or all the packets received are written. */ while (1) { /* * Rebuild the iovector only when the past vector has been completely written. Simplifies the logic quite a bit. */ written = 0; if (q->ioIndex == 0 && buildSendVec(q) <= 0) { break; } /* * Write the vector and file data. Exclude the file entry in the io vector. */ written = (int) mprSendFileToSocket(conn->sock, resp->file, q->ioPos, q->ioCount, q->iovec, q->ioIndex, NULL, 0); mprLog(q, 5, "Send connector written %d", written); if (written < 0) { errCode = mprGetError(); if (errCode == EAGAIN || errCode == EWOULDBLOCK) { maRequestWriteBlocked(conn); break; } if (errCode == EPIPE || errCode == ECONNRESET) { maDisconnectConn(conn); } else { mprLog(conn, 7, "mprSendFileToSocket failed, errCode %d", errCode); maDisconnectConn(conn); } freeSentPackets(q, MAXINT); break; } else if (written == 0) { /* Socket is full. Wait for an I/O event */ maRequestWriteBlocked(conn); break; } else if (written > 0) { resp->bytesWritten += written; freeSentPackets(q, written); adjustSendVec(q, written); } } if (q->ioCount == 0 && q->flags & MA_QUEUE_EOF) { maCompleteRequest(conn); } }
static void netOutgoingService(MaQueue *q) { MaConn *conn; MaResponse *resp; int written, errCode; conn = q->conn; resp = conn->response; while (q->first || q->ioIndex) { written = 0; if (q->ioIndex == 0 && buildNetVec(q) <= 0) { break; } /* * Issue a single I/O request to write all the blocks in the I/O vector */ errCode = mprGetOsError(); mprAssert(q->ioIndex > 0); written = mprWriteSocketVector(conn->sock, q->iovec, q->ioIndex); mprLog(q, 5, "Net connector written %d", written); if (written < 0) { errCode = mprGetOsError(); if (errCode == EAGAIN || errCode == EWOULDBLOCK) { maRequestWriteBlocked(conn); break; } if (errCode == EPIPE || errCode == ECONNRESET) { maDisconnectConn(conn); } else { mprLog(conn, 7, "mprVectorWriteSocket failed, error %d", errCode); maDisconnectConn(conn); } freeNetPackets(q, MAXINT); break; } else if (written == 0) { /* * Socket full. Wait for an I/O event. Conn.c will setup listening for write events if the queue is non-empty */ maRequestWriteBlocked(conn); break; } else if (written > 0) { resp->bytesWritten += written; freeNetPackets(q, written); adjustNetVec(q, written); } } if (q->ioCount == 0 && q->flags & MA_QUEUE_EOF) { maCompleteRequest(conn); } }
/* * Set the connection for disconnection when the I/O event returns. Setting keepAliveCount to zero will cause a * server-led disconnection. */ void maDisconnectConn(MaConn *conn) { conn->canProceed = 0; conn->disconnected = 1; conn->keepAliveCount = 0; conn->requestFailed = 1; if (conn->response) { mprLog(conn, 4, "Disconnect conn fd %d", conn->sock ? conn->sock->fd : 0); maCompleteRequest(conn); maDiscardPipeData(conn); } }