void Process::handleInput(int fd)
{
    EventLoop::instance()->removeFileDescriptor(fd);

    //static int ting = 0;
    //printf("Process::handleInput (cnt=%d)\n", ++ting);
    for (;;) {
        if (mStdInBuffer.empty())
            return;

        //printf("Process::handleInput in loop\n");
        int w, want;
        const ByteArray& front = mStdInBuffer.front();
        if (mStdInIndex) {
            want = front.size() - mStdInIndex;
            eintrwrap(w, ::write(fd, front.mid(mStdInIndex).constData(), want));
        } else {
            want = front.size();
            eintrwrap(w, ::write(fd, front.constData(), want));
        }
        if (w == -1) {
            EventLoop::instance()->addFileDescriptor(fd, EventLoop::Write, processCallback, this);
            break;
        } else if (w == want) {
            mStdInBuffer.pop_front();
            mStdInIndex = 0;
        } else
            mStdInIndex += w;
    }
}
Beispiel #2
0
void Process::finish(int returnCode)
{
    {
        std::lock_guard<std::mutex> lock(mMutex);
        mReturn = returnCode;

        mStdInBuffer.clear();
        closeStdIn(CloseForce);
        mWantStdInClosed = false;

        if (mMode == Async) {
            // try to read all remaining data on stdout and stderr
            handleOutput(mStdOut[0], mStdOutBuffer, mStdOutIndex, mReadyReadStdOut);
            handleOutput(mStdErr[0], mStdErrBuffer, mStdErrIndex, mReadyReadStdErr);

            closeStdOut();
            closeStdErr();
        } else {
            int w;
            char q = 'q';
            eintrwrap(w, ::write(mSync[1], &q, 1));
            eintrwrap(w, ::close(mSync[1]));
            mSync[1] = -1;
        }
    }

    if (mMode == Async)
        mFinished(this);
}
Beispiel #3
0
void Process::handleInput(int fd)
{
    assert(EventLoop::eventLoop());
    EventLoop::eventLoop()->unregisterSocket(fd);

    //static int ting = 0;
    //printf("Process::handleInput (cnt=%d)\n", ++ting);
    for (;;) {
        if (mStdInBuffer.empty())
            return;

        //printf("Process::handleInput in loop\n");
        int w, want;
        const String& front = mStdInBuffer.front();
        if (mStdInIndex) {
            want = front.size() - mStdInIndex;
            eintrwrap(w, ::write(fd, front.mid(mStdInIndex).constData(), want));
        } else {
            want = front.size();
            eintrwrap(w, ::write(fd, front.constData(), want));
        }
        if (w == -1) {
            EventLoop::eventLoop()->registerSocket(fd, EventLoop::SocketWrite, std::bind(&Process::processCallback, this, std::placeholders::_1, std::placeholders::_2));
            break;
        } else if (w == want) {
            mStdInBuffer.pop_front();
            mStdInIndex = 0;
        } else
            mStdInIndex += w;
    }
}
Beispiel #4
0
static inline bool connectInternal(int &fd, int domain, sockaddr* address, size_t addressSize, int maxTime)
{
    StopWatch timer;

    while (true) {
        fd = ::socket(domain, SOCK_STREAM, 0);
        if (fd == -1)
            return false;

        addFlags(fd, O_NONBLOCK);
        errno = 0;
        int ret;
        eintrwrap(ret, ::connect(fd, address, addressSize));
        if (!ret) {
#ifdef HAVE_NOSIGPIPE
            ret = 1;
            ::setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&ret, sizeof(int));
#endif
            return true;
        }

        int left = -1;
        if (maxTime >= 0) {
            left = maxTime - static_cast<int>(timer.elapsed());
            if (left <= 0)
                break;
        }

        if (errno == EINPROGRESS) {
            fd_set write;
            FD_ZERO(&write);
            FD_SET(fd, &write);
            timeval timeout;
            if (left != -1) {
                timeout.tv_sec = left / 1000;
                timeout.tv_usec = (left % 1000) * 1000;
            }
            eintrwrap(ret, select(fd + 1, 0, &write, 0, left == -1 ? 0 : &timeout));
            if (ret > 0 && FD_ISSET(fd, &write)) {
                int error;
                socklen_t len = sizeof(error);
                if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) && !error)
                    return true;
            }
            break;
        } else if (errno == EAGAIN) {
            eintrwrap(ret, ::close(fd));
            fd = -1;
            usleep(100000);
        } else {
            break;
        }
    }
    if (fd != -1) {
        int ret;
        eintrwrap(ret, ::close(fd));
        fd = -1;
    }
    return false;
}
Beispiel #5
0
void Process::clear()
{
    // don't clear a running process please
    assert(mPid == -1);

    if (mStdIn[0] != -1 && EventLoop::eventLoop()) {
        // try to finish off any pending writes
        handleInput(mStdIn[1]);
    }

    closeStdIn(CloseForce);
    closeStdOut();
    closeStdErr();

    int w;
    if (mSync[0] != -1)
        eintrwrap(w, ::close(mSync[0]));
    if (mSync[1] != -1)
        eintrwrap(w, ::close(mSync[1]));

    mReturn = ReturnUnset;
    mStdInIndex = mStdOutIndex = mStdErrIndex = 0;
    mWantStdInClosed = false;
    mMode = Sync;
}
Beispiel #6
0
static inline void addFlags(int fd, int flags)
{
    int ret;
    eintrwrap(ret, fcntl(fd, F_GETFL, 0));
    if (ret != -1)
        flags |= ret;
    eintrwrap(ret, fcntl(fd, F_SETFL, flags));
}
Beispiel #7
0
LocalClient::LocalClient(int fd)
    : mFd(fd), mBufferIdx(0), mReadBufferPos(0)
{
    int flags;
    eintrwrap(flags, fcntl(mFd, F_GETFL, 0));
    eintrwrap(flags, fcntl(mFd, F_SETFL, flags | O_NONBLOCK));
#ifdef HAVE_NOSIGPIPE
    flags = 1;
    ::setsockopt(mFd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&flags, sizeof(int));
#endif
    EventLoop::instance()->addFileDescriptor(mFd, EventLoop::Read, dataCallback, this);
}
Beispiel #8
0
bool LocalClient::writeMore()
{
    bool ret = true;
    int written = 0;
#ifdef HAVE_NOSIGNAL
    const int sendflags = MSG_NOSIGNAL;
#else
    const int sendflags = 0;
#endif
    for (;;) {
        if (mBuffers.empty()) {
            EventLoop::instance()->removeFileDescriptor(mFd, EventLoop::Write);
            break;
        }
        const String& front = mBuffers.front();
        int w;
        eintrwrap(w, ::send(mFd, &front[mBufferIdx], front.size() - mBufferIdx, sendflags));

        if (w == -1) {
            ret = (errno == EWOULDBLOCK || errno == EAGAIN); // apparently these can be different
            break;
        }
        written += w;
        mBufferIdx += w;
        if (mBufferIdx == front.size()) {
            assert(!mBuffers.empty());
            mBuffers.pop_front();
            mBufferIdx = 0;
            continue;
        }
    }
    if (written)
        mBytesWritten(this, written);
    return ret;
}
Beispiel #9
0
void SocketServer::socketCallback(int /*fd*/, int mode)
{
    sockaddr_in client4;
    sockaddr_in6 client6;
    sockaddr* client = 0;
    socklen_t size = 0;
    if (isIPv6) {
        size = sizeof(client6);
        client = reinterpret_cast<sockaddr*>(&client6);
    } else {
        size = sizeof(client4);
        client = reinterpret_cast<sockaddr*>(&client4);
    }
    int e;

    if (! ( mode & EventLoop::SocketRead ) )
        return;

    for (;;) {
        eintrwrap(e, ::accept(fd, client, &size));
        if (e == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                return;
            }
            serverError(this, AcceptError);
            close();
            return;
        }

        //EventLoop::eventLoop()->unregisterSocket( fd );
        accepted.push(e);
        serverNewConnection(this);
    }
}
bool LocalClient::connect(const Path& path, int maxTime)
{
    if (!path.isSocket())
        return false;
    StopWatch timer;
    struct sockaddr_un address;
    memset(&address, 0, sizeof(struct sockaddr_un));
    address.sun_family = AF_UNIX;
    const int sz = std::min<int>(sizeof(address.sun_path) - 1, path.size());
    memcpy(address.sun_path, path.constData(), sz);
    address.sun_path[sz] = '\0';
    while (true) {
        mFd = ::socket(PF_UNIX, SOCK_STREAM, 0);
        if (mFd == -1) {
            Path::rm(path);
            return false;
        }
        int ret;
        eintrwrap(ret, ::connect(mFd, (struct sockaddr *)&address, sizeof(struct sockaddr_un)));
        if (!ret) {
#ifdef HAVE_NOSIGPIPE
            ret = 1;
            ::setsockopt(mFd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&ret, sizeof(int));
#endif
            break;
        }
        eintrwrap(ret, ::close(mFd));
        mFd = -1;
        if (maxTime > 0 && timer.elapsed() >= maxTime) {
            Path::rm(path);
            return false;
        }
    }

    assert(mFd != -1);
    int flags;
    eintrwrap(flags, fcntl(mFd, F_GETFL, 0));
    eintrwrap(flags, fcntl(mFd, F_SETFL, flags | O_NONBLOCK));

    unsigned int fdflags = EventLoop::Read;
    if (!mBuffers.empty())
        fdflags |= EventLoop::Write;
    EventLoop::instance()->addFileDescriptor(mFd, fdflags, dataCallback, this);

    mConnected(this);
    return true;
}
Beispiel #11
0
ProcessThread::ProcessThread()
{
    ::signal(SIGCHLD, ProcessThread::processSignalHandler);

    int flg;
    eintrwrap(flg, ::pipe(sProcessPipe));
    SocketClient::setFlags(sProcessPipe[1], O_NONBLOCK, F_GETFL, F_SETFL);
}
Beispiel #12
0
void Semaphore::op(short num)
{
    sembuf buf = { 0, num, SEM_UNDO };
    int ret;
    eintrwrap(ret, semop(mSem, &buf, 1));
    if (ret == -1 && errno == EIDRM)
        mSem = -1;
}
Beispiel #13
0
static void signalHandler(int sig)
{
    char b = 'q';
    int w;
    const int pipe = mainEventPipe;
    if (pipe != -1)
        eintrwrap(w, ::write(pipe, &b, 1));
}
Beispiel #14
0
void Semaphore::acquire(short num)
{
    sembuf buf = { 0, static_cast<short>(num * -1), SEM_UNDO };
    int ret;
    eintrwrap(ret, semop(mSem, &buf, 1));
    if (ret == -1 && errno == EIDRM)
        mSem = -1;
}
ProcessThread::ProcessThread()
{
    int flg;
    eintrwrap(flg, ::pipe(sProcessPipe));
    eintrwrap(flg, ::fcntl(sProcessPipe[1], F_GETFL, 0));
    eintrwrap(flg, ::fcntl(sProcessPipe[1], F_SETFL, flg | O_NONBLOCK));

#ifdef HAVE_SIGINFO
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = ProcessThread::processSignalHandler;
    sa.sa_flags = SA_RESTART | SA_SIGINFO;
    ::sigaction(SIGCHLD, &sa, 0);
#else
    ::signal(SIGCHLD, ProcessThread::processSignalHandler);
#endif
}
Beispiel #16
0
void ProcessThread::run()
{
    ssize_t r;
    for (;;) {
        char ch;
        r = ::read(sProcessPipe[0], &ch, sizeof(char));
        if (r == 1) {
            if (ch == 's') {
                break;
            } else {
                int ret;
                pid_t p;
                std::unique_lock<std::mutex> lock(sProcessMutex);
                bool done = false;
                do {
                    //printf("testing pid %d\n", proc->first);
                    eintrwrap(p, ::waitpid(0, &ret, WNOHANG));
                    switch(p) {
                    case 0:
                        // we're done
                        done = true;
                        break;
                    case -1:
                        done = true;
                        if (errno == ECHILD)
                            break;
                        // this is bad
                        error() << "waitpid error" << errno;
                        break;
                    default:
                        //printf("successfully waited for pid (got %d)\n", p);
                        if (WIFEXITED(ret)) {
                            ret = WEXITSTATUS(ret);
                        } else {
                            ret = Process::ReturnCrashed;
                        }
                        auto proc = sProcesses.find(p);
                        if (proc != sProcesses.end()) {
                            Process *process = proc->second.proc;
                            EventLoop::SharedPtr loop = proc->second.loop.lock();
                            sProcesses.erase(proc++);
                            lock.unlock();
                            if (loop) {
                                loop->callLater([process, ret]() { process->finish(ret); });
                            } else {
                                process->finish(ret);
                            }
                            lock.lock();
                        } else {
                            error() << "couldn't find process for pid" << p;
                        }
                    }
                } while (!done);
            }
        }
    }
    //printf("process thread died for some reason\n");
}
Beispiel #17
0
void EventLoop::wakeup()
{
    if (std::this_thread::get_id() == threadId)
        return;

    char b = 'w';
    int w;
    eintrwrap(w, ::write(eventPipe[1], &b, 1));
}
Beispiel #18
0
void SocketClient::disconnect()
{
    if (mFd != -1) {
        int ret;
        eintrwrap(ret, ::close(mFd));
        EventLoop::instance()->removeFileDescriptor(mFd);
        mFd = -1;
        mDisconnected(this);
    }
}
void Process::closeStdErr()
{
    if (mStdErr[0] == -1)
        return;

    EventLoop::instance()->removeFileDescriptor(mStdErr[0]);
    int err;
    eintrwrap(err, ::close(mStdErr[0]));
    mStdErr[0] = -1;
}
Beispiel #20
0
void Process::closeStdErr()
{
    if (mStdErr[0] == -1)
        return;

    EventLoop::eventLoop()->unregisterSocket(mStdErr[0]);
    int err;
    eintrwrap(err, ::close(mStdErr[0]));
    mStdErr[0] = -1;
}
Beispiel #21
0
void Process::closeStdOut()
{
    if (mStdOut[0] == -1)
        return;

    if (EventLoop::SharedPtr eventLoop = EventLoop::eventLoop())
        eventLoop->unregisterSocket(mStdOut[0]);
    int err;
    eintrwrap(err, ::close(mStdOut[0]));
    mStdOut[0] = -1;
}
Beispiel #22
0
Process::~Process()
{
    if (mPid != -1)
        ProcessThread::removePid(mPid);

    if (mStdIn[0] != -1) {
        // try to finish off any pending writes
        handleInput(mStdIn[1]);
    }

    closeStdIn();
    closeStdOut();
    closeStdErr();

    int w;
    if (mSync[0] != -1)
        eintrwrap(w, ::close(mSync[0]));
    if (mSync[1] != -1)
        eintrwrap(w, ::close(mSync[1]));
}
Beispiel #23
0
bool SocketClient::writeMore()
{
    bool ret = true;
    int written = 0;
#ifdef HAVE_NOSIGNAL
    const int sendflags = MSG_NOSIGNAL;
#else
    const int sendflags = 0;
#endif
    for (;;) {
        if (mBuffers.empty()) {
            EventLoop::instance()->removeFileDescriptor(mFd, EventLoop::Write);
            break;
        }
        const sockaddr_in& addr = mBuffers.front().first;
        const String& front = mBuffers.front().second;
        int w;
        if (!addr.sin_port) {
            eintrwrap(w, ::send(mFd, &front[mBufferIdx], front.size() - mBufferIdx, sendflags));
        } else {
            eintrwrap(w, ::sendto(mFd, &front[mBufferIdx], front.size() - mBufferIdx, sendflags,
                                  reinterpret_cast<const sockaddr*>(&addr), sizeof(sockaddr_in)));
        }

        if (w == -1) {
            ret = (errno == EWOULDBLOCK || errno == EAGAIN); // apparently these can be different
            break;
        }
        written += w;
        mBufferIdx += w;
        if (mBufferIdx == front.size()) {
            assert(!mBuffers.empty());
            mBuffers.pop_front();
            mBufferIdx = 0;
            continue;
        }
    }
    if (written)
        mBytesWritten(this, written);
    return ret;
}
Beispiel #24
0
Process::~Process()
{
    {
        std::lock_guard<std::mutex> lock(mMutex);
        assert(mReturn != ReturnUnset || mPid == -1);
    }

    if (mStdIn[0] != -1 && EventLoop::eventLoop()) {
        // try to finish off any pending writes
        handleInput(mStdIn[1]);
    }

    closeStdIn(CloseForce);
    closeStdOut();
    closeStdErr();

    int w;
    if (mSync[0] != -1)
        eintrwrap(w, ::close(mSync[0]));
    if (mSync[1] != -1)
        eintrwrap(w, ::close(mSync[1]));
}
Beispiel #25
0
bool EventLoop::registerSocket(int fd, unsigned int mode, std::function<void(int, unsigned int)>&& func)
{
    std::lock_guard<std::mutex> locker(mutex);
    sockets[fd] = std::make_pair(mode, std::forward<std::function<void(int, unsigned int)> >(func));

    int e;
#if defined(HAVE_EPOLL)
    epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLET|EPOLLRDHUP;
    if (mode & SocketRead)
        ev.events |= EPOLLIN;
    if (mode & SocketWrite)
        ev.events |= EPOLLOUT;
    if (mode & SocketOneShot)
        ev.events |= EPOLLONESHOT;
    ev.data.fd = fd;
    e = epoll_ctl(pollFd, EPOLL_CTL_ADD, fd, &ev);
#elif defined(HAVE_KQUEUE)
    const struct { int rf; int kf; } flags[] = {
        { SocketRead, EVFILT_READ },
        { SocketWrite, EVFILT_WRITE },
        { 0, 0 }
    };
    for (int i = 0; flags[i].rf; ++i) {
        if (!(mode & flags[i].rf))
            continue;
        struct kevent ev;
        memset(&ev, '\0', sizeof(struct kevent));
        ev.ident = fd;
        ev.flags = EV_ADD|EV_ENABLE;
        if (mode & SocketOneShot)
            ev.flags |= EV_ONESHOT;
        ev.filter = flags[i].kf;
        eintrwrap(e, kevent(pollFd, &ev, 1, 0, 0, 0));
    }
#elif defined(HAVE_SELECT)
    e = 0; // fake ok
    wakeup();
#endif
    if (e == -1) {
        if (errno != EEXIST) {
            fprintf(stderr, "Unable to register socket %d with mode %x: %d (%s)\n", fd, mode, errno, rct_strerror(errno));
            return false;
        }
    }
    return true;
}
Beispiel #26
0
void Process::closeStdIn(CloseStdInFlag flag)
{
    if (mStdIn[1] == -1)
        return;

    if (flag == CloseForce || mStdInBuffer.empty()) {
        if (EventLoop::SharedPtr loop = EventLoop::eventLoop())
            loop->unregisterSocket(mStdIn[1]);
        int err;
        eintrwrap(err, ::close(mStdIn[1]));
        mStdIn[1] = -1;
        mWantStdInClosed = false;
    } else {
        mWantStdInClosed = true;
    }
}
Beispiel #27
0
void Process::handleOutput(int fd, String &buffer, int &index, Signal<std::function<void(Process*)> > &signal)
{
    //printf("Process::handleOutput %d\n", fd);
    enum { BufSize = 1024, MaxSize = (1024 * 1024 * 256) };
    char buf[BufSize];
    int total = 0;
    for (;;) {
        int r;
        eintrwrap(r, ::read(fd, buf, BufSize));
        if (r == -1) {
            //printf("Process::handleOutput %d returning -1, errno %d %s\n", fd, errno, Rct::strerror().constData());
            break;
        } else if (r == 0) { // file descriptor closed, remove it
            //printf("Process::handleOutput %d returning 0\n", fd);
            if (auto eventLoop = EventLoop::eventLoop())
                eventLoop->unregisterSocket(fd);
            break;
        } else {
            //printf("Process::handleOutput in loop %d\n", fd);
            //printf("data: '%s'\n", String(buf, r).constData());
            int sz = buffer.size();
            if (sz + r > MaxSize) {
                if (sz + r - index > MaxSize) {
                    error("Process::handleOutput, buffer too big, dropping data");
                    buffer.clear();
                    index = sz = 0;
                } else {
                    sz = buffer.size() - index;
                    memmove(buffer.data(), buffer.data() + index, sz);
                    buffer.resize(sz);
                    index = 0;
                }
            }
            buffer.resize(sz + r);
            memcpy(buffer.data() + sz, buf, r);

            total += r;
        }
    }

    //printf("total data '%s'\n", buffer.nullTerminated());

    if (total)
        signal(this);
}
void Process::handleOutput(int fd, ByteArray& buffer, int& index, signalslot::Signal0& signal)
{
    //printf("Process::handleOutput %d\n", fd);
    enum { BufSize = 1024, MaxSize = (1024 * 1024 * 16) };
    char buf[BufSize];
    int total = 0;
    for (;;) {
        int r;
        eintrwrap(r, ::read(fd, buf, BufSize));
        if (r == -1) {
            //printf("Process::handleOutput %d returning -1, errno %d %s\n", fd, errno, strerror(errno));
            break;
        } else if (r == 0) { // file descriptor closed, remove it
            //printf("Process::handleOutput %d returning 0\n", fd);
            EventLoop::instance()->removeFileDescriptor(fd);
            break;
        } else {
            //printf("Process::handleOutput in loop %d\n", fd);
            //printf("data: '%s'\n", std::string(buf, r).c_str());
            int sz = buffer.size();
            if (sz + r > MaxSize) {
                if (sz + r - index > MaxSize) {
                    error("Process::handleOutput, buffer too big, dropping data");
                    buffer.clear();
                    index = sz = 0;
                } else {
                    sz = buffer.size() - index;
                    memmove(buffer.data(), buffer.data() + index, sz);
                    buffer.resize(sz);
                    index = 0;
                }
            }
            buffer.resize(sz + r);
            memcpy(buffer.data() + sz, buf, r);

            total += r;
        }
    }

    //printf("total data '%s'\n", buffer.nullTerminated());

    if (total)
        signal();
}
Beispiel #29
0
void EventLoop::unregisterSocket(int fd)
{
    std::lock_guard<std::mutex> locker(mutex);
    auto socket = sockets.find(fd);
    if (socket == sockets.end())
        return;
#ifdef HAVE_KQUEUE
    const int mode = socket->second.first;
#endif
    sockets.erase(socket);

    int e;
#if defined(HAVE_EPOLL)
    epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    e = epoll_ctl(pollFd, EPOLL_CTL_DEL, fd, &ev);
#elif defined(HAVE_KQUEUE)
    const struct { int rf; int kf; } flags[] = {
        { SocketRead, EVFILT_READ },
        { SocketWrite, EVFILT_WRITE },
        { 0, 0 }
    };
    for (int i = 0; flags[i].rf; ++i) {
        if (!(mode & flags[i].rf))
            continue;
        struct kevent ev;
        memset(&ev, '\0', sizeof(struct kevent));
        ev.ident = fd;
        ev.flags = EV_DELETE|EV_DISABLE;
        ev.filter = flags[i].kf;
        eintrwrap(e, kevent(pollFd, &ev, 1, 0, 0, 0));
    }
#elif defined(HAVE_SELECT)
    e = 0; // fake ok
    wakeup();
#endif
    if (e == -1) {
        if (errno != ENOENT) {
            fprintf(stderr, "Unable to unregister socket %d: %d (%s)\n", fd, errno, rct_strerror(errno));
        }
    }
}
Beispiel #30
0
void LocalClient::readMore()
{
    enum { BufSize = 1024, MaxBufferSize = 1024 * 1024 * 16 };

#ifdef HAVE_NOSIGNAL
    const int recvflags = MSG_NOSIGNAL;
#else
    const int recvflags = 0;
#endif
    char buf[BufSize];
    int read = 0;
    bool wasDisconnected = false;
    for (;;) {
        int r;
        eintrwrap(r, ::recv(mFd, buf, BufSize, recvflags));

        if (r == -1) {
            break;
        } else if (!r) {
            wasDisconnected = true;
            break;
        }
        read += r;
        mReadBuffer.resize(r + mReadBuffer.size());
        memcpy(mReadBuffer.data() + mReadBuffer.size() - r, buf, r);
        if (mReadBuffer.size() + r >= MaxBufferSize) {
            if (mReadBuffer.size() + r - mReadBufferPos < MaxBufferSize) {
                mReadBuffer.remove(0, mReadBufferPos);
                mReadBufferPos = 0;
            } else {
                error("Buffer exhausted (%d), dropping on the floor", mReadBuffer.size());
                mReadBuffer.clear();
            }
        }
    }

    if (read && !mReadBuffer.isEmpty())
        mDataAvailable(this);
    if (wasDisconnected)
        disconnect();
}