Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c8e452d authored by Mike Yu's avatar Mike Yu
Browse files

Add some states to trace DnsTlsSocket life cycle

The state diagram of DnsTlsSocket is simple and doesn't have
circular states.

Bug: 149445907
Test: cd packages/modules/DnsResolver && atest
Change-Id: I5088d3c6e3c9d3c148cfce4ffa97218bab7e0e78
parent f6b64093
Loading
Loading
Loading
Loading
+19 −7
Original line number Diff line number Diff line
@@ -173,28 +173,28 @@ bool DnsTlsSocket::initialize() {

    mEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));

    transitionState(State::UNINITIALIZED, State::INITIALIZED);

    return true;
}

bool DnsTlsSocket::startHandshake() {
    std::lock_guard guard(mLock);
    if (!mSslCtx) {
        LOG(ERROR) << "Calling startHandshake before initializing";
        return false;
    }

    if (mLoopThread) {
        LOG(WARNING) << "The loop thread has been created. Ignore the handshake request";
    if (mState != State::INITIALIZED) {
        LOG(ERROR) << "Calling startHandshake in unexpected state " << static_cast<int>(mState);
        return false;
    }
    transitionState(State::INITIALIZED, State::CONNECTING);

    // Connect
    Status status = tcpConnect();
    if (!status.ok()) {
        transitionState(State::CONNECTING, State::WAIT_FOR_DELETE);
        return false;
    }
    mSsl = sslConnect(mSslFd.get());
    if (!mSsl) {
        transitionState(State::CONNECTING, State::WAIT_FOR_DELETE);
        return false;
    }

@@ -326,7 +326,9 @@ void DnsTlsSocket::loop() {
    std::deque<std::vector<uint8_t>> q;
    const int timeout_msecs = DnsTlsSocket::kIdleTimeout.count() * 1000;

    transitionState(State::CONNECTING, State::CONNECTED);
    setThreadName(StringPrintf("TlsListen_%u", mMark & 0xffff).c_str());

    while (true) {
        // poll() ignores negative fds
        struct pollfd fds[2] = { { .fd = -1 }, { .fd = -1 } };
@@ -396,6 +398,7 @@ void DnsTlsSocket::loop() {
    sslDisconnect();
    LOG(DEBUG) << "Calling onClosed";
    mObserver->onClosed();
    transitionState(State::CONNECTED, State::WAIT_FOR_DELETE);
    LOG(DEBUG) << "Ending loop";
}

@@ -458,6 +461,15 @@ bool DnsTlsSocket::incrementEventFd(const int64_t count) {
    return true;
}

void DnsTlsSocket::transitionState(State from, State to) {
    if (mState != from) {
        LOG(WARNING) << "BUG: transitioning from an unexpected state " << static_cast<int>(mState)
                     << ", expect: from " << static_cast<int>(from) << " to "
                     << static_cast<int>(to);
    }
    mState = to;
}

// Read exactly len bytes into buffer or fail with an SSL error code
int DnsTlsSocket::sslRead(const Slice buffer, bool wait) {
    size_t remaining = buffer.size();
+19 −4
Original line number Diff line number Diff line
@@ -47,26 +47,37 @@ class DnsTlsSessionCache;
//
// Calls to IDnsTlsSocketObserver in a DnsTlsSocket life cycle:
//
//                                    START
//                                UNINITIALIZED
//                                      |
//                                      v
//                            +--startHandshake()--+
//                                 INITIALIZED
//                                      |
//                                      v
//                            +----CONNECTING------+
//            Handshake fails |                    | Handshake succeeds
//                            |                    |
//                            |                    v
//                            |        +--------> loop --+
//                            |        +---> CONNECTED --+
//                            |        |           |     |
//                            |        +-----------+     | Idle timeout
//                            |   Send/Recv queries      | onClose()
//                            |   onResponse()           |
//                            |                          |
//                            |                          |
//                            +------> END <-------------+
//                            +--> WAIT_FOR_DELETE <-----+
//
//
// TODO: Add onHandshakeFinished() for handshake results.
class DnsTlsSocket : public IDnsTlsSocket {
  public:
    enum class State {
        UNINITIALIZED,
        INITIALIZED,
        CONNECTING,
        CONNECTED,
        WAIT_FOR_DELETE,
    };

    DnsTlsSocket(const DnsTlsServer& server, unsigned mark,
                 IDnsTlsSocketObserver* _Nonnull observer, DnsTlsSessionCache* _Nonnull cache)
        : mMark(mark), mServer(server), mObserver(observer), mCache(cache) {}
@@ -136,6 +147,9 @@ class DnsTlsSocket : public IDnsTlsSocket {
    // the loop thread by incrementing mEventFd.  loop() reads items off the queue.
    LockedQueue<std::vector<uint8_t>> mQueue;

    // Transition the state from expected state |from| to new state |to|.
    void transitionState(State from, State to) REQUIRES(mLock);

    // eventfd socket used for notifying the SSL thread when queries are ready to send.
    // This socket acts similarly to an atomic counter, incremented by query() and cleared
    // by loop().  We have to use a socket because the SSL thread needs to wait in poll()
@@ -155,6 +169,7 @@ class DnsTlsSocket : public IDnsTlsSocket {
    const DnsTlsServer mServer;
    IDnsTlsSocketObserver* _Nonnull const mObserver;
    DnsTlsSessionCache* _Nonnull const mCache;
    State mState GUARDED_BY(mLock) = State::UNINITIALIZED;
};

}  // end of namespace net