Пример #1
0
/*
 *  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);
    }
}
Пример #2
0
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);
    }
}
Пример #3
0
/*
 *  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);
    }
}