libbinder: Add inet support.
Test: binderRpcTest
Bug: 182914638
Change-Id: Idf70050060d708e919ce0e828b58e77aa6032563
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
index 4aff92b..22e0466 100644
--- a/libs/binder/RpcConnection.cpp
+++ b/libs/binder/RpcConnection.cpp
@@ -18,6 +18,16 @@
#include <binder/RpcConnection.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <string_view>
+
#include <binder/Parcel.h>
#include <binder/Stability.h>
#include <utils/String8.h>
@@ -25,11 +35,6 @@
#include "RpcState.h"
#include "RpcWireFormat.h"
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
#ifdef __GLIBC__
extern "C" pid_t gettid();
#endif
@@ -41,6 +46,7 @@
namespace android {
using base::unique_fd;
+using AddrInfo = std::unique_ptr<addrinfo, decltype(&freeaddrinfo)>;
RpcConnection::SocketAddress::~SocketAddress() {}
@@ -120,6 +126,70 @@
#endif // __BIONIC__
+class SocketAddressImpl : public RpcConnection::SocketAddress {
+public:
+ SocketAddressImpl(const sockaddr* addr, size_t size, const String8& desc)
+ : mAddr(addr), mSize(size), mDesc(desc) {}
+ [[nodiscard]] std::string toString() const override {
+ return std::string(mDesc.c_str(), mDesc.size());
+ }
+ [[nodiscard]] const sockaddr* addr() const override { return mAddr; }
+ [[nodiscard]] size_t addrSize() const override { return mSize; }
+ void set(const sockaddr* addr, size_t size) {
+ mAddr = addr;
+ mSize = size;
+ }
+
+private:
+ const sockaddr* mAddr = nullptr;
+ size_t mSize = 0;
+ String8 mDesc;
+};
+
+AddrInfo GetAddrInfo(const char* addr, unsigned int port) {
+ addrinfo hint{
+ .ai_flags = 0,
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM,
+ .ai_protocol = 0,
+ };
+ addrinfo* aiStart = nullptr;
+ if (int rc = getaddrinfo(addr, std::to_string(port).data(), &hint, &aiStart); 0 != rc) {
+ ALOGE("Unable to resolve %s:%u: %s", addr, port, gai_strerror(rc));
+ return AddrInfo(nullptr, nullptr);
+ }
+ if (aiStart == nullptr) {
+ ALOGE("Unable to resolve %s:%u: getaddrinfo returns null", addr, port);
+ return AddrInfo(nullptr, nullptr);
+ }
+ return AddrInfo(aiStart, &freeaddrinfo);
+}
+
+bool RpcConnection::setupInetServer(unsigned int port) {
+ auto aiStart = GetAddrInfo("127.0.0.1", port);
+ if (aiStart == nullptr) return false;
+ SocketAddressImpl socketAddress(nullptr, 0, String8::format("127.0.0.1:%u", port));
+ for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
+ socketAddress.set(ai->ai_addr, ai->ai_addrlen);
+ if (setupSocketServer(socketAddress)) return true;
+ }
+ ALOGE("None of the socket address resolved for 127.0.0.1:%u can be set up as inet server.",
+ port);
+ return false;
+}
+
+bool RpcConnection::addInetClient(const char* addr, unsigned int port) {
+ auto aiStart = GetAddrInfo(addr, port);
+ if (aiStart == nullptr) return false;
+ SocketAddressImpl socketAddress(nullptr, 0, String8::format("%s:%u", addr, port));
+ for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
+ socketAddress.set(ai->ai_addr, ai->ai_addrlen);
+ if (addSocketClient(socketAddress)) return true;
+ }
+ ALOGE("None of the socket address resolved for %s:%u can be added as inet client.", addr, port);
+ return false;
+}
+
bool RpcConnection::addNullDebuggingClient() {
unique_fd serverFd(TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC)));
diff --git a/libs/binder/include/binder/RpcConnection.h b/libs/binder/include/binder/RpcConnection.h
index dba47b4..1763d10 100644
--- a/libs/binder/include/binder/RpcConnection.h
+++ b/libs/binder/include/binder/RpcConnection.h
@@ -74,6 +74,16 @@
#endif // __BIONIC__
/**
+ * Creates an RPC server at the current port.
+ */
+ [[nodiscard]] bool setupInetServer(unsigned int port);
+
+ /**
+ * Connects to an RPC server at the given address and port.
+ */
+ [[nodiscard]] bool addInetClient(const char* addr, unsigned int port);
+
+ /**
* For debugging!
*
* Sets up an empty socket. All queries to this socket which require a
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 3340293..ec4ced2 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -257,6 +257,7 @@
#ifdef __BIONIC__
VSOCK,
#endif // __BIONIC__
+ INET,
};
static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) {
switch (info.param) {
@@ -266,6 +267,8 @@
case SocketType::VSOCK:
return "vm_socket";
#endif // __BIONIC__
+ case SocketType::INET:
+ return "inet_socket";
default:
LOG_ALWAYS_FATAL("Unknown socket type");
return "";
@@ -305,6 +308,9 @@
CHECK(connection->setupVsockServer(port));
break;
#endif // __BIONIC__
+ case SocketType::INET:
+ CHECK(connection->setupInetServer(port));
+ break;
default:
LOG_ALWAYS_FATAL("Unknown socket type");
}
@@ -335,6 +341,9 @@
if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, port)) goto success;
break;
#endif // __BIONIC__
+ case SocketType::INET:
+ if (ret.connection->addInetClient("127.0.0.1", port)) goto success;
+ break;
default:
LOG_ALWAYS_FATAL("Unknown socket type");
}
@@ -852,12 +861,13 @@
}
INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc,
- ::testing::Values(SocketType::UNIX
+ ::testing::ValuesIn({
+ SocketType::UNIX,
#ifdef __BIONIC__
- ,
- SocketType::VSOCK
+ SocketType::VSOCK,
#endif // __BIONIC__
- ),
+ SocketType::INET,
+ }),
PrintSocketType);
} // namespace android