Merge libnetddns into libnetd_resolv

libnetddns is the library for DNS-over-TLS and is statically
linked to netd. Deprecate it and move them to libnetd_resolv
as a more general DNS library for netd.

This change comprises:

[1] Clean up netd/server/dns/*. Move all DnsTls* files to
    netd/resolv/ to parts of libnetd_resolv library.

[2] Export DnsTls* classes being visible for netd. It will only
    be temporary for a while.

[3] Remove the libssl dependency in netd. The relevant stuff is
    moved to libnetd_resolv.

Note that DnsTls* classes are still required for DnsProxyListener
and ResolverController to manipulate private DNS servers even after
this change.

Bug: 113628807
Test: as follows
    - built, flashed, booted
    - system/netd/tests/runtests.sh
    - DNS-over-TLS in live network passed

Change-Id: Ieac5889b4ebe737f876b3dcbe1a8da2b2b1b629d
diff --git a/resolv/include/netd_resolv/DnsTlsDispatcher.h b/resolv/include/netd_resolv/DnsTlsDispatcher.h
new file mode 100644
index 0000000..0bb19f2
--- /dev/null
+++ b/resolv/include/netd_resolv/DnsTlsDispatcher.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_DNSTLSDISPATCHER_H
+#define _DNS_DNSTLSDISPATCHER_H
+
+#include <list>
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <android-base/thread_annotations.h>
+
+#include <netdutils/Slice.h>
+
+#include "DnsTlsServer.h"
+#include "DnsTlsTransport.h"
+#include "IDnsTlsSocketFactory.h"
+#include "params.h"
+
+namespace android {
+namespace net {
+
+using netdutils::Slice;
+
+// This is a singleton class that manages the collection of active DnsTlsTransports.
+// Queries made here are dispatched to an existing or newly constructed DnsTlsTransport.
+class LIBNETD_RESOLV_TLS_EXPORT DnsTlsDispatcher {
+public:
+    // Default constructor.
+    DnsTlsDispatcher();
+
+    // Constructor with dependency injection for testing.
+    explicit DnsTlsDispatcher(std::unique_ptr<IDnsTlsSocketFactory> factory) :
+            mFactory(std::move(factory)) {}
+
+    // Enqueues |query| for resolution via the given |tlsServers| on the
+    // network indicated by |mark|; writes the response into |ans|, and stores
+    // the count of bytes written in |resplen|. Returns a success or error code.
+    // The order in which servers from |tlsServers| are queried may not be the
+    // order passed in by the caller.
+    DnsTlsTransport::Response query(const std::list<DnsTlsServer> &tlsServers, unsigned mark,
+                                    const Slice query, const Slice ans, int * _Nonnull resplen);
+
+    // Given a |query|, sends it to the server on the network indicated by |mark|,
+    // and writes the response into |ans|,  and indicates
+    // the number of bytes written in |resplen|.  Returns a success or error code.
+    DnsTlsTransport::Response query(const DnsTlsServer& server, unsigned mark,
+                                    const Slice query, const Slice ans, int * _Nonnull resplen);
+
+private:
+    // This lock is static so that it can be used to annotate the Transport struct.
+    // DnsTlsDispatcher is a singleton in practice, so making this static does not change
+    // the locking behavior.
+    static std::mutex sLock;
+
+    // Key = <mark, server>
+    typedef std::pair<unsigned, const DnsTlsServer> Key;
+
+    // Transport is a thin wrapper around DnsTlsTransport, adding reference counting and
+    // usage monitoring so we can expire idle sessions from the cache.
+    struct Transport {
+        Transport(const DnsTlsServer& server, unsigned mark,
+                  IDnsTlsSocketFactory* _Nonnull factory) :
+                transport(server, mark, factory) {}
+        // DnsTlsTransport is thread-safe, so it doesn't need to be guarded.
+        DnsTlsTransport transport;
+        // This use counter and timestamp are used to ensure that only idle sessions are
+        // destroyed.
+        int useCount GUARDED_BY(sLock) = 0;
+        // lastUsed is only guaranteed to be meaningful after useCount is decremented to zero.
+        std::chrono::time_point<std::chrono::steady_clock> lastUsed GUARDED_BY(sLock);
+    };
+
+    // Cache of reusable DnsTlsTransports.  Transports stay in cache as long as
+    // they are in use and for a few minutes after.
+    // The key is a (netid, server) pair.  The netid is first for lexicographic comparison speed.
+    std::map<Key, std::unique_ptr<Transport>> mStore GUARDED_BY(sLock);
+
+    // The last time we did a cleanup.  For efficiency, we only perform a cleanup once every
+    // few minutes.
+    std::chrono::time_point<std::chrono::steady_clock> mLastCleanup GUARDED_BY(sLock);
+
+    // Drop any cache entries whose useCount is zero and which have not been used recently.
+    // This function performs a linear scan of mStore.
+    void cleanup(std::chrono::time_point<std::chrono::steady_clock> now) REQUIRES(sLock);
+
+    // Return a sorted list of DnsTlsServers in preference order.
+    std::list<DnsTlsServer> getOrderedServerList(
+            const std::list<DnsTlsServer> &tlsServers, unsigned mark) const;
+
+    // Trivial factory for DnsTlsSockets.  Dependency injection is only used for testing.
+    std::unique_ptr<IDnsTlsSocketFactory> mFactory;
+};
+
+}  // end of namespace net
+}  // end of namespace android
+
+#endif  // _DNS_DNSTLSDISPATCHER_H
diff --git a/resolv/include/netd_resolv/DnsTlsQueryMap.h b/resolv/include/netd_resolv/DnsTlsQueryMap.h
new file mode 100644
index 0000000..4c8010c
--- /dev/null
+++ b/resolv/include/netd_resolv/DnsTlsQueryMap.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_DNSTLSQUERYMAP_H
+#define _DNS_DNSTLSQUERYMAP_H
+
+#include <future>
+#include <map>
+#include <mutex>
+#include <vector>
+
+#include <android-base/thread_annotations.h>
+#include <netdutils/Slice.h>
+
+#include "DnsTlsServer.h"
+#include "params.h"
+
+namespace android {
+namespace net {
+
+using netdutils::Slice;
+
+// Keeps track of queries and responses.  This class matches responses with queries.
+// All methods are thread-safe and non-blocking.
+class LIBNETD_RESOLV_TLS_EXPORT DnsTlsQueryMap {
+public:
+    struct Query {
+        // The new ID number assigned to this query.
+        uint16_t newId;
+        // A query that has been passed to recordQuery(), with its original ID number.
+        const Slice query;
+    };
+
+    typedef DnsTlsServer::Response Response;
+    typedef DnsTlsServer::Result Result;
+
+    struct QueryFuture {
+        QueryFuture(Query query, std::future<Result> result) :
+                query(query), result(std::move(result)) {}
+        Query query;
+        // A future which will resolve to the result of this query.
+        std::future<Result> result;
+    };
+
+    // Returns an object containing everything needed to complete processing of
+    // this query, or null if the query could not be recorded.
+    std::unique_ptr<QueryFuture> recordQuery(const Slice query);
+
+    // Process a response, including a new ID.  If the response
+    // is not recognized as matching any query, it will be ignored.
+    void onResponse(std::vector<uint8_t> response);
+
+    // Clear all map contents.  This causes all pending queries to resolve with failure.
+    void clear();
+
+    // Get all pending queries.  This returns a shallow copy, mostly for thread-safety.
+    std::vector<Query> getAll();
+
+    // Mark a query has having been retried.  If the query hits the retry limit, it will
+    // be expired at the next call to cleanup.
+    void markTried(uint16_t newId);
+    void cleanup();
+
+    // Returns true if there are no pending queries.
+    bool empty();
+
+private:
+    std::mutex mLock;
+
+    struct QueryPromise {
+        QueryPromise(Query query) : query(query) {}
+        Query query;
+        // Number of times the query has been tried.  Limited to kMaxTries.
+        int tries = 0;
+        // A promise whose future is returned by recordQuery()
+        // It is fulfilled by onResponse().
+        std::promise<Result> result;
+    };
+
+    // The maximum number of times we will send a query before abandoning it.
+    static constexpr int kMaxTries = 3;
+
+    // Outstanding queries by newId.
+    std::map<uint16_t, QueryPromise> mQueries GUARDED_BY(mLock);
+
+    // Get a "newId" number that is not currently in use.  Returns -1 if there are none.
+    int32_t getFreeId() REQUIRES(mLock);
+
+    // Fulfill the result with an error code.
+    static void expire(QueryPromise* _Nonnull p);
+};
+
+}  // end of namespace net
+}  // end of namespace android
+
+#endif  // _DNS_DNSTLSQUERYMAP_H
diff --git a/resolv/include/netd_resolv/DnsTlsServer.h b/resolv/include/netd_resolv/DnsTlsServer.h
new file mode 100644
index 0000000..752dc5f
--- /dev/null
+++ b/resolv/include/netd_resolv/DnsTlsServer.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_DNSTLSSERVER_H
+#define _DNS_DNSTLSSERVER_H
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include <netinet/in.h>
+
+#include "params.h"
+
+namespace android {
+namespace net {
+
+// DnsTlsServer represents a recursive resolver that supports, or may support, a
+// secure protocol.
+struct LIBNETD_RESOLV_TLS_EXPORT DnsTlsServer {
+    // Default constructor.
+    DnsTlsServer() {}
+
+    // Allow sockaddr_storage to be promoted to DnsTlsServer automatically.
+    DnsTlsServer(const sockaddr_storage& ss) : ss(ss) {}
+
+    enum class Response : uint8_t { success, network_error, limit_error, internal_error };
+
+    struct Result {
+        Response code;
+        std::vector<uint8_t> response;
+    };
+
+    // The server location, including IP and port.
+    sockaddr_storage ss = {};
+
+    // A set of SHA256 public key fingerprints.  If this set is nonempty, the server
+    // must present a self-consistent certificate chain that contains a certificate
+    // whose public key matches one of these fingerprints.  Otherwise, the client will
+    // terminate the connection.
+    std::set<std::vector<uint8_t>> fingerprints;
+
+    // The server's hostname.  If this string is nonempty, the server must present a
+    // certificate that indicates this name and has a valid chain to a trusted root CA.
+    std::string name;
+
+    // Placeholder.  More protocols might be defined in the future.
+    int protocol = IPPROTO_TCP;
+
+    // Exact comparison of DnsTlsServer objects
+    bool operator <(const DnsTlsServer& other) const;
+    bool operator ==(const DnsTlsServer& other) const;
+
+    bool wasExplicitlyConfigured() const;
+};
+
+// This comparison only checks the IP address.  It ignores ports, names, and fingerprints.
+struct LIBNETD_RESOLV_TLS_EXPORT AddressComparator {
+    bool operator() (const DnsTlsServer& x, const DnsTlsServer& y) const;
+};
+
+}  // namespace net
+}  // namespace android
+
+#endif  // _DNS_DNSTLSSERVER_H
diff --git a/resolv/include/netd_resolv/DnsTlsSessionCache.h b/resolv/include/netd_resolv/DnsTlsSessionCache.h
new file mode 100644
index 0000000..8d0fc1d
--- /dev/null
+++ b/resolv/include/netd_resolv/DnsTlsSessionCache.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_DNSTLSSESSIONCACHE_H
+#define _DNS_DNSTLSSESSIONCACHE_H
+
+#include <deque>
+#include <mutex>
+
+#include <openssl/ssl.h>
+
+#include <android-base/thread_annotations.h>
+#include <android-base/unique_fd.h>
+
+#include "params.h"
+
+namespace android {
+namespace net {
+
+// Cache of recently seen SSL_SESSIONs.  This is used to support session tickets.
+// This class is thread-safe.
+class DnsTlsSessionCache {
+public:
+    // Prepare SSL objects to use this session cache.  These methods must be called
+    // before making use of either object.
+    void prepareSslContext(SSL_CTX* _Nonnull ssl_ctx);
+    bool prepareSsl(SSL* _Nonnull ssl);
+
+    // Get the most recently discovered session.  For TLS 1.3 compatibility and
+    // maximum privacy, each session will only be returned once, so the caller
+    // gains ownership of the session.  (Here and throughout,
+    // bssl::UniquePtr<SSL_SESSION> is actually serving as a reference counted
+    // pointer.)
+    bssl::UniquePtr<SSL_SESSION> getSession() EXCLUDES(mLock);
+
+private:
+    static constexpr size_t kMaxSize = 5;
+    static int newSessionCallback(SSL* _Nullable ssl, SSL_SESSION* _Nullable session);
+
+    std::mutex mLock;
+    void recordSession(SSL_SESSION* _Nullable session) EXCLUDES(mLock);
+
+    // Queue of sessions, from least recently added to most recently.
+    std::deque<bssl::UniquePtr<SSL_SESSION>> mSessions GUARDED_BY(mLock);
+};
+
+}  // end of namespace net
+}  // end of namespace android
+
+#endif  // _DNS_DNSTLSSESSIONCACHE_H
diff --git a/resolv/include/netd_resolv/DnsTlsSocket.h b/resolv/include/netd_resolv/DnsTlsSocket.h
new file mode 100644
index 0000000..7190dd2
--- /dev/null
+++ b/resolv/include/netd_resolv/DnsTlsSocket.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_DNSTLSSOCKET_H
+#define _DNS_DNSTLSSOCKET_H
+
+#include <future>
+#include <mutex>
+#include <openssl/ssl.h>
+
+#include <android-base/thread_annotations.h>
+#include <android-base/unique_fd.h>
+#include <netdutils/Slice.h>
+#include <netdutils/Status.h>
+
+#include "DnsTlsServer.h"
+#include "IDnsTlsSocket.h"
+#include "params.h"
+
+namespace android {
+namespace net {
+
+class IDnsTlsSocketObserver;
+class DnsTlsSessionCache;
+
+using netdutils::Slice;
+
+// A class for managing a TLS socket that sends and receives messages in
+// [length][value] format, with a 2-byte length (i.e. DNS-over-TCP format).
+// This class is not aware of query-response pairing or anything else about DNS.
+// For the observer:
+// This class is not re-entrant: the observer is not permitted to wait for a call to query()
+// or the destructor in a callback.  Doing so will result in deadlocks.
+// This class may call the observer at any time after initialize(), until the destructor
+// returns (but not after).
+class LIBNETD_RESOLV_TLS_EXPORT DnsTlsSocket : public IDnsTlsSocket {
+public:
+    DnsTlsSocket(const DnsTlsServer& server, unsigned mark,
+                 IDnsTlsSocketObserver* _Nonnull observer,
+                 DnsTlsSessionCache* _Nonnull cache) :
+            mMark(mark), mServer(server), mObserver(observer), mCache(cache) {}
+    ~DnsTlsSocket();
+
+    // Creates the SSL context for this session and connect.  Returns false on failure.
+    // This method should be called after construction and before use of a DnsTlsSocket.
+    // Only call this method once per DnsTlsSocket.
+    bool initialize() EXCLUDES(mLock);
+
+    // Send a query on the provided SSL socket.  |query| contains
+    // the body of a query, not including the ID header. This function will typically return before
+    // the query is actually sent.  If this function fails, DnsTlsSocketObserver will be
+    // notified that the socket is closed.
+    // Note that success here indicates successful sending, not receipt of a response.
+    // Thread-safe.
+    bool query(uint16_t id, const Slice query) override;
+
+private:
+    // Lock to be held by the SSL event loop thread.  This is not normally in contention.
+    std::mutex mLock;
+
+    // Forwards queries and receives responses.  Blocks until the idle timeout.
+    void loop() EXCLUDES(mLock);
+    std::unique_ptr<std::thread> mLoopThread GUARDED_BY(mLock);
+
+    // On success, sets mSslFd to a socket connected to mAddr (the
+    // connection will likely be in progress if mProtocol is IPPROTO_TCP).
+    // On error, returns the errno.
+    netdutils::Status tcpConnect() REQUIRES(mLock);
+
+    // Connect an SSL session on the provided socket.  If connection fails, closing the
+    // socket remains the caller's responsibility.
+    bssl::UniquePtr<SSL> sslConnect(int fd) REQUIRES(mLock);
+
+    // Disconnect the SSL session and close the socket.
+    void sslDisconnect() REQUIRES(mLock);
+
+    // Writes a buffer to the socket.
+    bool sslWrite(const Slice buffer) REQUIRES(mLock);
+
+    // Reads exactly the specified number of bytes from the socket, or fails.
+    // Returns SSL_ERROR_NONE on success.
+    // If |wait| is true, then this function always blocks.  Otherwise, it
+    // will return SSL_ERROR_WANT_READ if there is no data from the server to read.
+    int sslRead(const Slice buffer, bool wait) REQUIRES(mLock);
+
+    struct Query {
+        uint16_t id;
+        Slice query;
+    };
+
+    bool sendQuery(const Query& q) REQUIRES(mLock);
+    bool readResponse() REQUIRES(mLock);
+
+    // SOCK_SEQPACKET socket pair used for sending queries from myriad query
+    // threads to the SSL thread.  EOF indicates a close request.
+    // We have to use a socket pair (i.e. a pipe) because the SSL thread needs
+    // to wait in poll() for input from either a remote server or a query thread.
+    base::unique_fd mIpcInFd;
+    base::unique_fd mIpcOutFd GUARDED_BY(mLock);
+
+    // SSL Socket fields.
+    bssl::UniquePtr<SSL_CTX> mSslCtx GUARDED_BY(mLock);
+    base::unique_fd mSslFd GUARDED_BY(mLock);
+    bssl::UniquePtr<SSL> mSsl GUARDED_BY(mLock);
+    static constexpr std::chrono::seconds kIdleTimeout = std::chrono::seconds(20);
+
+    const unsigned mMark;  // Socket mark
+    const DnsTlsServer mServer;
+    IDnsTlsSocketObserver* _Nonnull const mObserver;
+    DnsTlsSessionCache* _Nonnull const mCache;
+};
+
+}  // end of namespace net
+}  // end of namespace android
+
+#endif  // _DNS_DNSTLSSOCKET_H
diff --git a/resolv/include/netd_resolv/DnsTlsSocketFactory.h b/resolv/include/netd_resolv/DnsTlsSocketFactory.h
new file mode 100644
index 0000000..1c58535
--- /dev/null
+++ b/resolv/include/netd_resolv/DnsTlsSocketFactory.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_DNSTLSSOCKETFACTORY_H
+#define _DNS_DNSTLSSOCKETFACTORY_H
+
+#include <memory>
+
+#include "DnsTlsSocket.h"
+#include "IDnsTlsSocketFactory.h"
+
+namespace android {
+namespace net {
+
+class IDnsTlsSocketObserver;
+class DnsTlsSessionCache;
+struct DnsTlsServer;
+
+// Trivial RAII factory for DnsTlsSocket.  This is owned by DnsTlsDispatcher.
+class DnsTlsSocketFactory : public IDnsTlsSocketFactory {
+public:
+    std::unique_ptr<IDnsTlsSocket> createDnsTlsSocket(const DnsTlsServer& server, unsigned mark,
+                                                     IDnsTlsSocketObserver* _Nonnull observer,
+                                                     DnsTlsSessionCache* _Nonnull cache) override {
+        auto socket = std::make_unique<DnsTlsSocket>(server, mark, observer, cache);
+        if (!socket->initialize()) {
+            return nullptr;
+        }
+        return std::move(socket);
+    }
+};
+
+}  // end of namespace net
+}  // end of namespace android
+
+#endif  // _DNS_DNSTLSSOCKETFACTORY_H
diff --git a/resolv/include/netd_resolv/DnsTlsTransport.h b/resolv/include/netd_resolv/DnsTlsTransport.h
new file mode 100644
index 0000000..0d314ad
--- /dev/null
+++ b/resolv/include/netd_resolv/DnsTlsTransport.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_DNSTLSTRANSPORT_H
+#define _DNS_DNSTLSTRANSPORT_H
+
+#include <future>
+#include <map>
+#include <mutex>
+#include <vector>
+
+#include <android-base/thread_annotations.h>
+#include <android-base/unique_fd.h>
+
+#include "DnsTlsQueryMap.h"
+#include "DnsTlsServer.h"
+#include "DnsTlsSessionCache.h"
+#include "IDnsTlsSocket.h"
+#include "IDnsTlsSocketObserver.h"
+#include "params.h"
+
+#include <netdutils/Slice.h>
+
+namespace android {
+namespace net {
+
+class IDnsTlsSocketFactory;
+
+// Manages at most one DnsTlsSocket at a time.  This class handles socket lifetime issues,
+// such as reopening the socket and reissuing pending queries.
+class LIBNETD_RESOLV_TLS_EXPORT DnsTlsTransport : public IDnsTlsSocketObserver {
+public:
+    DnsTlsTransport(const DnsTlsServer& server, unsigned mark,
+                    IDnsTlsSocketFactory* _Nonnull factory) :
+            mMark(mark), mServer(server), mFactory(factory) {}
+    ~DnsTlsTransport();
+
+    typedef DnsTlsServer::Response Response;
+    typedef DnsTlsServer::Result Result;
+
+    // Given a |query|, this method sends it to the server and returns the result asynchronously.
+    std::future<Result> query(const netdutils::Slice query) EXCLUDES(mLock);
+
+    // Check that a given TLS server is fully working on the specified netid, and has the
+    // provided SHA-256 fingerprint (if nonempty).  This function is used in ResolverController
+    // to ensure that we don't enable DNS over TLS on networks where it doesn't actually work.
+    static bool validate(const DnsTlsServer& server, unsigned netid);
+
+    // Implement IDnsTlsSocketObserver
+    void onResponse(std::vector<uint8_t> response) override;
+    void onClosed() override EXCLUDES(mLock);
+
+private:
+    std::mutex mLock;
+
+    DnsTlsSessionCache mCache;
+    DnsTlsQueryMap mQueries;
+
+    const unsigned mMark;  // Socket mark
+    const DnsTlsServer mServer;
+    IDnsTlsSocketFactory* _Nonnull const mFactory;
+
+    void doConnect() REQUIRES(mLock);
+
+    // doReconnect is used by onClosed.  It runs on the reconnect thread.
+    void doReconnect() EXCLUDES(mLock);
+    std::unique_ptr<std::thread> mReconnectThread GUARDED_BY(mLock);
+
+    // Used to prevent onClosed from starting a reconnect during the destructor.
+    bool mClosing GUARDED_BY(mLock) = false;
+
+    // Sending queries on the socket is thread-safe, but construction/destruction is not.
+    std::unique_ptr<IDnsTlsSocket> mSocket GUARDED_BY(mLock);
+
+    // Send a query to the socket.
+    bool sendQuery(const DnsTlsQueryMap::Query q) REQUIRES(mLock);
+};
+
+}  // end of namespace net
+}  // end of namespace android
+
+#endif  // _DNS_DNSTLSTRANSPORT_H
diff --git a/resolv/include/netd_resolv/IDnsTlsSocket.h b/resolv/include/netd_resolv/IDnsTlsSocket.h
new file mode 100644
index 0000000..4f21bbd
--- /dev/null
+++ b/resolv/include/netd_resolv/IDnsTlsSocket.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_IDNSTLSSOCKET_H
+#define _DNS_IDNSTLSSOCKET_H
+
+#include <cstddef>
+#include <cstdint>
+
+#include <netdutils/Slice.h>
+
+namespace android {
+namespace net {
+
+class IDnsTlsSocketObserver;
+class DnsTlsSessionCache;
+
+// A class for managing a TLS socket that sends and receives messages in
+// [length][value] format, with a 2-byte length (i.e. DNS-over-TCP format).
+// This interface is not aware of query-response pairing or anything else about DNS.
+class IDnsTlsSocket {
+public:
+    virtual ~IDnsTlsSocket() {};
+    // Send a query on the provided SSL socket.  |query| contains
+    // the body of a query, not including the ID bytes.  This function will typically return before
+    // the query is actually sent.  If this function fails, the observer will be
+    // notified that the socket is closed.
+    // Note that a true return value indicates successful sending, not receipt of a response.
+    virtual bool query(uint16_t id, const netdutils::Slice query) = 0;
+};
+
+}  // end of namespace net
+}  // end of namespace android
+
+#endif  // _DNS_IDNSTLSSOCKET_H
diff --git a/resolv/include/netd_resolv/IDnsTlsSocketFactory.h b/resolv/include/netd_resolv/IDnsTlsSocketFactory.h
new file mode 100644
index 0000000..52164b6
--- /dev/null
+++ b/resolv/include/netd_resolv/IDnsTlsSocketFactory.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_IDNSTLSSOCKETFACTORY_H
+#define _DNS_IDNSTLSSOCKETFACTORY_H
+
+#include "IDnsTlsSocket.h"
+
+namespace android {
+namespace net {
+
+class IDnsTlsSocketObserver;
+class DnsTlsSessionCache;
+struct DnsTlsServer;
+
+// Dependency injection interface for DnsTlsSocketFactory.
+// This pattern allows mocking of DnsTlsSocket for tests.
+class IDnsTlsSocketFactory {
+public:
+    virtual ~IDnsTlsSocketFactory() {};
+    virtual std::unique_ptr<IDnsTlsSocket> createDnsTlsSocket(
+            const DnsTlsServer& server,
+            unsigned mark,
+            IDnsTlsSocketObserver* _Nonnull observer,
+            DnsTlsSessionCache* _Nonnull cache) = 0;
+};
+
+}  // end of namespace net
+}  // end of namespace android
+
+#endif  // _DNS_IDNSTLSSOCKETFACTORY_H
diff --git a/resolv/include/netd_resolv/IDnsTlsSocketObserver.h b/resolv/include/netd_resolv/IDnsTlsSocketObserver.h
new file mode 100644
index 0000000..7ae364c
--- /dev/null
+++ b/resolv/include/netd_resolv/IDnsTlsSocketObserver.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_IDNSTLSSOCKETOBSERVER_H
+#define _DNS_IDNSTLSSOCKETOBSERVER_H
+
+namespace android {
+namespace net {
+
+// Interface to listen for DNS query responses on a socket, and to be notified
+// when the socket is closed by the remote peer.  This is only implemented by
+// DnsTlsTransport, but it is a separate interface for clarity and to avoid a
+// circular dependency with DnsTlsSocket.
+class IDnsTlsSocketObserver {
+public:
+    virtual ~IDnsTlsSocketObserver() {};
+    virtual void onResponse(std::vector<uint8_t> response) = 0;
+
+    virtual void onClosed() = 0;
+};
+
+}  // namespace net
+}  // namespace android
+
+#endif  // _DNS_IDNSTLSSOCKETOBSERVER_H
diff --git a/resolv/include/netd_resolv/params.h b/resolv/include/netd_resolv/params.h
index 60b9b54..c3f3363 100644
--- a/resolv/include/netd_resolv/params.h
+++ b/resolv/include/netd_resolv/params.h
@@ -46,4 +46,7 @@
 
 #define LIBNETD_RESOLV_PUBLIC extern "C" [[gnu::visibility("default")]]
 
+// TODO: Remove it after we move PrivateDnsConfiguration and qhook() into libnetd_resolv.
+#define LIBNETD_RESOLV_TLS_EXPORT [[gnu::visibility("default")]]
+
 #endif  // NETD_RESOLV_PARAMS_H