Пример #1
0
void AsynchConnector::connComplete(DispatchHandle& h)
{
    int errCode = socket.getError();
    if (errCode == 0) {
        h.stopWatch();
        try {
            socket.finishConnect(sa);
        } catch (const std::exception& e) {
            failCallback(socket, 0, e.what());
            DispatchHandle::doDelete();
            return;
        }
        connCallback(socket);
    } else {
        // Retry while we cause an immediate exception
        // (asynch failure will be handled by re-entering here at the top)
        while (sa.nextAddress()) {
            try {
                // Try next address without deleting ourselves
                QPID_LOG(debug, "Ignored socket connect error: " << strError(errCode));
                QPID_LOG(info, "Retrying connect: " << sa.asString());
                socket.connect(sa);
                return;
            } catch (const std::exception& e) {
                QPID_LOG(debug, "Ignored socket connect exception: " << e.what());
            }
            errCode = socket.getError();
        }
        h.stopWatch();
        failCallback(socket, errCode, strError(errCode));
    }
    DispatchHandle::doDelete();
}
Пример #2
0
/*
 * Close the socket and callback to say we've done it
 */
void AsynchIO::close(DispatchHandle& h) {
    h.stopWatch();
    socket.close();
    if (closedCallback) {
        closedCallback(*this, socket);
    }
}
Пример #3
0
void SslIO::disconnected(DispatchHandle& h) {
    // If we've already queued close do it instead of disconnected callback
    if (queuedClose) {
        close(h);
    } else if (disCallback) {
        disCallback(*this);
        h.unwatch();
    }
}
Пример #4
0
void SslConnector::connComplete(DispatchHandle& h)
{
    int errCode = socket.getError();

    h.stopWatch();
    if (errCode == 0) {
        connCallback(socket);
        DispatchHandle::doDelete();
    } else {
        // TODO: This need to be fixed as strerror isn't thread safe
        failure(errCode, std::string(::strerror(errCode)));
    }
}
Пример #5
0
void SslAcceptorTmpl<T>::readable(DispatchHandle& h) {
    Socket* s;
    do {
        errno = 0;
        // TODO: Currently we ignore the peers address, perhaps we should
        // log it or use it for connection acceptance.
        try {
            s = socket.accept();
            if (s) {
                acceptedCallback(*s);
            } else {
                break;
            }
        } catch (const std::exception& e) {
            QPID_LOG(error, "Could not accept socket: " << e.what());
        }
    } while (true);

    h.rewatch();
}
Пример #6
0
/*
 * We carry on writing whilst we have data to write and we can write
 */
void AsynchIO::writeable(DispatchHandle& h) {
    AbsTime writeStartTime = AbsTime::now();
    size_t total = 0;
    int writeCalls = 0;
    do {
        // See if we've got something to write
        if (!writeQueue.empty()) {
            // Write buffer
            BufferBase* buff = writeQueue.back();
            writeQueue.pop_back();
            errno = 0;
            assert(buff->dataStart+buff->dataCount <= buff->byteCount);
            int rc = socket.write(buff->bytes+buff->dataStart, buff->dataCount);
            int64_t duration = Duration(writeStartTime, AbsTime::now());
            ++writeCalls;
            if (rc >= 0) {
                threadWriteTotal += rc;
                total += rc;

                // If we didn't write full buffer put rest back
                if (rc != buff->dataCount) {
                    buff->dataStart += rc;
                    buff->dataCount -= rc;
                    writeQueue.push_back(buff);
                    QPID_PROBE4(asynchio_write_finished_done, &h, duration, total, writeCalls);
                    break;
                }

                // Recycle the buffer
                queueReadBuffer(buff);

                // Stop writing if we've overrun our timeslot
                if (duration > threadMaxIoTimeNs) {
                    QPID_PROBE4(asynchio_write_finished_maxtime, &h, duration, total, writeCalls);
                    break;
                }
            } else {
                // Put buffer back
                writeQueue.push_back(buff);
                QPID_PROBE5(asynchio_write_finished_error, &h, duration, total, writeCalls, errno);

                if (errno == ECONNRESET || errno == EPIPE) {
                    // Just stop watching for write here - we'll get a
                    // disconnect callback soon enough
                    h.unwatchWrite();
                    break;
                } else if (errno == EAGAIN) {
                    // We have just put a buffer back so we know
                    // we can carry on watching for writes
                    break;
                } else {
                    // Report error then just treat as a socket disconnect
                    QPID_LOG(error, "Error writing socket: " << qpid::sys::strError(errno) << "(" << errno << ")" );
                    h.unwatchWrite();
                    break;
                }
            }
        } else {
            int64_t duration = Duration(writeStartTime, AbsTime::now());
            (void) duration; // force duration to be used if no probes are compiled

            // If we're waiting to close the socket then can do it now as there is nothing to write
            if (queuedClose) {
                close(h);
                QPID_PROBE4(asynchio_write_finished_closed, &h, duration, total, writeCalls);
                break;
            }
            // Fd is writable, but nothing to write
            if (idleCallback) {
                writePending = false;
                idleCallback(*this);
            }
            // If we still have no buffers to write we can't do anything more
            if (writeQueue.empty() && !writePending && !queuedClose) {
                h.unwatchWrite();
                // The following handles the case where writePending is
                // set to true after the test above; in this case its
                // possible that the unwatchWrite overwrites the
                // desired rewatchWrite so we correct that here
                if (writePending)
                    h.rewatchWrite();
                QPID_PROBE4(asynchio_write_finished_nodata, &h, duration, total, writeCalls);
                break;
            }
        }
    } while (true);

    ++threadWriteCount;
    return;
}
Пример #7
0
/*
 * We keep on reading as long as we have something to read, a buffer
 * to put it in and reading is not stopped by flow control.
 */
void AsynchIO::readable(DispatchHandle& h) {
    AbsTime readStartTime = AbsTime::now();
    size_t total = 0;
    int readCalls = 0;
    do {
        // (Try to) get a buffer
        if (!bufferQueue.empty()) {
            // Read into buffer
            BufferBase* buff = bufferQueue.front();
            assert(buff);
            bufferQueue.pop_front();
            errno = 0;
            int readCount = buff->byteCount-buff->dataCount;
            int rc = socket.read(buff->bytes + buff->dataCount, readCount);
            int64_t duration = Duration(readStartTime, AbsTime::now());
            ++readCalls;
            if (rc > 0) {
                buff->dataCount += rc;
                threadReadTotal += rc;
                total += rc;

                readCallback(*this, buff);
                if (rc != readCount) {
                    // If we didn't fill the read buffer then time to stop reading
                    QPID_PROBE4(asynchio_read_finished_done, &h, duration, total, readCalls);
                    break;
                }

                // Stop reading if we've overrun our timeslot
                if ( duration > threadMaxIoTimeNs) {
                    QPID_PROBE4(asynchio_read_finished_maxtime, &h, duration, total, readCalls);
                    break;
                }

            } else {
                // Put buffer back (at front so it doesn't interfere with unread buffers)
                bufferQueue.push_front(buff);
                assert(buff);

                QPID_PROBE5(asynchio_read_finished_error, &h, duration, total, readCalls, errno);
                // Eof or other side has gone away
                if (rc == 0 || errno == ECONNRESET) {
                    eofCallback(*this);
                    h.unwatchRead();
                    break;
                } else if (errno == EAGAIN) {
                    // We have just put a buffer back so we know
                    // we can carry on watching for reads
                    break;
                } else {
                    // Report error then just treat as a socket disconnect
                    QPID_LOG(error, "Error reading socket: " << qpid::sys::strError(errno) << "(" << errno << ")" );
                    eofCallback(*this);
                    h.unwatchRead();
                    break;
                }
            }
        } else {
            // Something to read but no buffer
            if (emptyCallback) {
                emptyCallback(*this);
            }
            // If we still have no buffers we can't do anything more
            if (bufferQueue.empty()) {
                h.unwatchRead();
                QPID_PROBE4(asynchio_read_finished_nobuffers, &h, Duration(readStartTime, AbsTime::now()), total, readCalls);
                break;
            }

        }
    } while (true);

    ++threadReadCount;
    return;
}
Пример #8
0
void AsynchAcceptor::start(Poller::shared_ptr poller) {
    handle.startWatch(poller);
}
Пример #9
0
void reader(DispatchHandle& h, int fd) {
    readBytes += readALot(fd);
    h.rewatch();
}
Пример #10
0
void writer(DispatchHandle& h, int fd, const string& s) {
    writtenBytes += writeALot(fd, s);
    h.rewatch();
}
Пример #11
0
/*
 * We carry on writing whilst we have data to write and we can write
 */
void SslIO::writeable(DispatchHandle& h) {
    AbsTime writeStartTime = AbsTime::now();
    do {
        // See if we've got something to write
        if (!writeQueue.empty()) {
            // Write buffer
            BufferBase* buff = writeQueue.back();
            writeQueue.pop_back();
            errno = 0;
            assert(buff->dataStart+buff->dataCount <= buff->byteCount);
            int rc = socket.write(buff->bytes+buff->dataStart, buff->dataCount);
            if (rc >= 0) {
                threadWriteTotal += rc;

                // If we didn't write full buffer put rest back
                if (rc != buff->dataCount) {
                    buff->dataStart += rc;
                    buff->dataCount -= rc;
                    writeQueue.push_back(buff);
                    break;
                }

                // Recycle the buffer
                queueReadBuffer(buff);

                // Stop writing if we've overrun our timeslot
                if (Duration(writeStartTime, AbsTime::now()) > threadMaxIoTimeNs) {
                    break;
                }
            } else {
                // Put buffer back
                writeQueue.push_back(buff);
                if (errno == ECONNRESET || errno == EPIPE) {
                    // Just stop watching for write here - we'll get a
                    // disconnect callback soon enough
                    h.unwatchWrite();
                    break;
                } else if (errno == EAGAIN) {
                    // We have just put a buffer back so we know
                    // we can carry on watching for writes
                    break;
                } else {
                    QPID_LOG(error, "Error writing to socket: " << getErrorString(PR_GetError()));
                    h.unwatchWrite();
                    break;
                }
            }
        } else {
            // If we're waiting to close the socket then can do it now as there is nothing to write
            if (queuedClose) {
                close(h);
                break;
            }
            // Fd is writable, but nothing to write
            if (idleCallback) {
                writePending = false;
                idleCallback(*this);
            }
            // If we still have no buffers to write we can't do anything more
            if (writeQueue.empty() && !writePending && !queuedClose) {
                h.unwatchWrite();
                // The following handles the case where writePending is
                // set to true after the test above; in this case its
                // possible that the unwatchWrite overwrites the
                // desired rewatchWrite so we correct that here
                if (writePending)
                    h.rewatchWrite();
                break;
            }
        }
    } while (true);

    ++threadWriteCount;
    return;
}
Пример #12
0
/*
 * We keep on reading as long as we have something to read and a buffer to put
 * it in
 */
void SslIO::readable(DispatchHandle& h) {
    AbsTime readStartTime = AbsTime::now();
    do {
        // (Try to) get a buffer
        if (!bufferQueue.empty()) {
            // Read into buffer
            BufferBase* buff = bufferQueue.front();
            assert(buff);
            bufferQueue.pop_front();
            errno = 0;
            int readCount = buff->byteCount-buff->dataCount;
            int rc = socket.read(buff->bytes + buff->dataCount, readCount);
            if (rc > 0) {
                buff->dataCount += rc;
                threadReadTotal += rc;

                readCallback(*this, buff);
                if (rc != readCount) {
                    // If we didn't fill the read buffer then time to stop reading
                    break;
                }

                // Stop reading if we've overrun our timeslot
                if (Duration(readStartTime, AbsTime::now()) > threadMaxIoTimeNs) {
                    break;
                }

            } else {
                // Put buffer back (at front so it doesn't interfere with unread buffers)
                bufferQueue.push_front(buff);
                assert(buff);

                // Eof or other side has gone away
                if (rc == 0 || errno == ECONNRESET) {
                    eofCallback(*this);
                    h.unwatchRead();
                    break;
                } else if (errno == EAGAIN) {
                    // We have just put a buffer back so we know
                    // we can carry on watching for reads
                    break;
                } else {
                    // Report error then just treat as a socket disconnect
                    QPID_LOG(error, "Error reading socket: " << getErrorString(PR_GetError()));
                    eofCallback(*this);
                    h.unwatchRead();
                    break;
                }
            }
        } else {
            // Something to read but no buffer
            if (emptyCallback) {
                emptyCallback(*this);
            }
            // If we still have no buffers we can't do anything more
            if (bufferQueue.empty()) {
                h.unwatchRead();
                break;
            }

        }
    } while (true);

    ++threadReadCount;
    return;
}