1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/client_channel_factory.h> 2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <errno.h> 4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <log/log.h> 5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/socket.h> 6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/un.h> 7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <unistd.h> 8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 94782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko#include <chrono> 104782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko#include <thread> 114782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko 12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/channel_manager.h> 13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/client_channel.h> 14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/ipc_helper.h> 15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 164782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenkousing std::chrono::duration_cast; 174782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenkousing std::chrono::steady_clock; 184782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko 19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android { 20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx { 21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace uds { 22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::string ClientChannelFactory::GetRootEndpointPath() { 24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return "/dev/socket/pdx"; 25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::string ClientChannelFactory::GetEndpointPath( 28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko const std::string& endpoint_path) { 29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::string path; 30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (!endpoint_path.empty()) { 31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (endpoint_path.front() == '/') 32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko path = endpoint_path; 33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko else 34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko path = GetRootEndpointPath() + '/' + endpoint_path; 35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return path; 37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoClientChannelFactory::ClientChannelFactory(const std::string& endpoint_path) 40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko : endpoint_path_{GetEndpointPath(endpoint_path)} {} 41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 426eefa42d33bdddc3603211634f98937b00abc532Alex VakulenkoClientChannelFactory::ClientChannelFactory(LocalHandle socket) 436eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko : socket_{std::move(socket)} {} 446eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko 45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::unique_ptr<pdx::ClientChannelFactory> ClientChannelFactory::Create( 46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko const std::string& endpoint_path) { 47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return std::unique_ptr<pdx::ClientChannelFactory>{ 48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko new ClientChannelFactory{endpoint_path}}; 49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 516eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenkostd::unique_ptr<pdx::ClientChannelFactory> ClientChannelFactory::Create( 526eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko LocalHandle socket) { 536eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko return std::unique_ptr<pdx::ClientChannelFactory>{ 546eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko new ClientChannelFactory{std::move(socket)}}; 556eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko} 566eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko 57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<std::unique_ptr<pdx::ClientChannel>> ClientChannelFactory::Connect( 58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko int64_t timeout_ms) const { 594782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko Status<void> status; 60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 616eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko bool connected = socket_.IsValid(); 626eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko if (!connected) { 63e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko socket_.Reset(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)); 646eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko LOG_ALWAYS_FATAL_IF( 656eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko endpoint_path_.empty(), 666eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko "ClientChannelFactory::Connect: unspecified socket path"); 676eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko } 686eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko 696eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko if (!socket_) { 704782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko ALOGE("ClientChannelFactory::Connect: socket error: %s", strerror(errno)); 71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return ErrorStatus(errno); 72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 744782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko bool use_timeout = (timeout_ms >= 0); 754782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko auto now = steady_clock::now(); 764782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko auto time_end = now + std::chrono::milliseconds{timeout_ms}; 774782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko 78c0fd676fa087b38b63d253536c6fc9513a0470c8Alex Vakulenko int max_eaccess = 5; // Max number of times to retry when EACCES returned. 794782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko while (!connected) { 804782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko int64_t timeout = -1; 814782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko if (use_timeout) { 824782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko auto remaining = time_end - now; 834782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko timeout = duration_cast<std::chrono::milliseconds>(remaining).count(); 844782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko if (timeout < 0) 854782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko return ErrorStatus(ETIMEDOUT); 864782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko } 876eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko sockaddr_un remote; 886eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko remote.sun_family = AF_UNIX; 896eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko strncpy(remote.sun_path, endpoint_path_.c_str(), sizeof(remote.sun_path)); 906eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko remote.sun_path[sizeof(remote.sun_path) - 1] = '\0'; 914782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko ALOGD("ClientChannelFactory: Waiting for endpoint at %s", remote.sun_path); 924782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko status = WaitForEndpoint(endpoint_path_, timeout); 934782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko if (!status) 944782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko return ErrorStatus(status.error()); 954782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko 964782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko ALOGD("ClientChannelFactory: Connecting to %s", remote.sun_path); 974782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko int ret = RETRY_EINTR(connect( 986eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko socket_.Get(), reinterpret_cast<sockaddr*>(&remote), sizeof(remote))); 994782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko if (ret == -1) { 1004782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko ALOGD("ClientChannelFactory: Connect error %d: %s", errno, 1014782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko strerror(errno)); 102c0fd676fa087b38b63d253536c6fc9513a0470c8Alex Vakulenko // if |max_eaccess| below reaches zero when errno is EACCES, the control 103c0fd676fa087b38b63d253536c6fc9513a0470c8Alex Vakulenko // flows into the next "else if" statement and a permanent error is 104c0fd676fa087b38b63d253536c6fc9513a0470c8Alex Vakulenko // returned from this function. 105c0fd676fa087b38b63d253536c6fc9513a0470c8Alex Vakulenko if (errno == ECONNREFUSED || (errno == EACCES && max_eaccess-- > 0)) { 106c0fd676fa087b38b63d253536c6fc9513a0470c8Alex Vakulenko // Connection refused/Permission denied can be the result of connecting 107c0fd676fa087b38b63d253536c6fc9513a0470c8Alex Vakulenko // too early (the service socket is created but its access rights are 108c0fd676fa087b38b63d253536c6fc9513a0470c8Alex Vakulenko // not set or not being listened to yet). 109c0fd676fa087b38b63d253536c6fc9513a0470c8Alex Vakulenko ALOGD("ClientChannelFactory: %s, waiting...", strerror(errno)); 1104782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko using namespace std::literals::chrono_literals; 1114782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko std::this_thread::sleep_for(100ms); 1124782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko } else if (errno != ENOENT && errno != ENOTDIR) { 1134782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko // ENOENT/ENOTDIR might mean that the socket file/directory containing 1144782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko // it has been just deleted. Try to wait for its creation and do not 1154782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko // return an error immediately. 1164782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko ALOGE( 1174782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko "ClientChannelFactory::Connect: Failed to initialize connection " 1184782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko "when connecting: %s", 1194782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko strerror(errno)); 1204782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko return ErrorStatus(errno); 1214782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko } 1224782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko } else { 1234782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko connected = true; 1246eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko ALOGD("ClientChannelFactory: Connected successfully to %s...", 1256eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko remote.sun_path); 126e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko ChannelConnectionInfo<LocalHandle> connection_info; 127e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko status = ReceiveData(socket_.Borrow(), &connection_info); 128e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko if (!status) 129e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko return status.error_status(); 130e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko socket_ = std::move(connection_info.channel_fd); 131e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko if (!socket_) { 132e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko ALOGE("ClientChannelFactory::Connect: Failed to obtain channel socket"); 133e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko return ErrorStatus(EIO); 134e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko } 1354782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko } 1364782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko if (use_timeout) 1374782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko now = steady_clock::now(); 1384782814b340bb55a0fbff9f7b6cfd4d27cffd85aAlex Vakulenko } // while (!connected) 139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko RequestHeader<BorrowedHandle> request; 141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false); 14252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka 1436eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko status = SendData(socket_.Borrow(), request); 144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (!status) 145e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko return status.error_status(); 14652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka 147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ResponseHeader<LocalHandle> response; 1486eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko status = ReceiveData(socket_.Borrow(), &response); 149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (!status) 150e41826ac301b9afad1cbfe59c57e27f2495be968Alex Vakulenko return status.error_status(); 15152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka else if (response.ret_code < 0 || response.channels.size() != 1) 15252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka return ErrorStatus(EIO); 15352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka 15452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka LocalHandle pollin_event_fd = std::move(response.channels[0].pollin_event_fd); 15552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka LocalHandle pollhup_event_fd = 15652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka std::move(response.channels[0].pollhup_event_fd); 15752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka 15852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka if (!pollin_event_fd || !pollhup_event_fd) { 15952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka ALOGE( 16052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka "ClientChannelFactory::Connect: Required fd was not returned from the " 16152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka "service: pollin_event_fd=%d pollhup_event_fd=%d", 16252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka pollin_event_fd.Get(), pollhup_event_fd.Get()); 163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return ErrorStatus(EIO); 16452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka } 165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return ClientChannel::Create(ChannelManager::Get().CreateHandle( 16752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka std::move(socket_), std::move(pollin_event_fd), 16852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka std::move(pollhup_event_fd))); 169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace uds 172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace pdx 173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace android 174