1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "client/pairing/pairing_client.h" 18 19 #include <atomic> 20 #include <iomanip> 21 #include <mutex> 22 #include <sstream> 23 #include <thread> 24 #include <vector> 25 26 #include <android-base/logging.h> 27 #include <android-base/parsenetaddress.h> 28 #include <android-base/stringprintf.h> 29 #include <android-base/thread_annotations.h> 30 #include <android-base/unique_fd.h> 31 #include <cutils/sockets.h> 32 #include "sysdeps.h" 33 34 namespace adbwifi { 35 namespace pairing { 36 37 using android::base::unique_fd; 38 39 namespace { 40 41 struct ConnectionDeleter { 42 void operator()(PairingConnectionCtx* p) { pairing_connection_destroy(p); } 43 }; // ConnectionDeleter 44 using ConnectionPtr = std::unique_ptr<PairingConnectionCtx, ConnectionDeleter>; 45 46 class PairingClientImpl : public PairingClient { 47 public: 48 virtual ~PairingClientImpl(); 49 50 explicit PairingClientImpl(const Data& pswd, const PeerInfo& peer_info, const Data& cert, 51 const Data& priv_key); 52 53 // Starts the pairing client. This call is non-blocking. Upon pairing 54 // completion, |cb| will be called with the PeerInfo on success, 55 // or an empty value on failure. 56 // 57 // Returns true if PairingClient was successfully started. Otherwise, 58 // return false. 59 virtual bool Start(std::string_view ip_addr, pairing_client_result_cb cb, 60 void* opaque) override; 61 62 static void OnPairingResult(const PeerInfo* peer_info, int fd, void* opaque); 63 64 private: 65 // Setup and start the PairingConnection 66 bool StartConnection(); 67 68 enum class State { 69 Ready, 70 Running, 71 Stopped, 72 }; 73 74 State state_ = State::Ready; 75 Data pswd_; 76 PeerInfo peer_info_; 77 Data cert_; 78 Data priv_key_; 79 std::string host_; 80 int port_; 81 82 ConnectionPtr connection_; 83 pairing_client_result_cb cb_; 84 void* opaque_ = nullptr; 85 }; // PairingClientImpl 86 87 PairingClientImpl::PairingClientImpl(const Data& pswd, const PeerInfo& peer_info, const Data& cert, 88 const Data& priv_key) 89 : pswd_(pswd), peer_info_(peer_info), cert_(cert), priv_key_(priv_key) { 90 CHECK(!pswd_.empty() && !cert_.empty() && !priv_key_.empty()); 91 92 state_ = State::Ready; 93 } 94 95 PairingClientImpl::~PairingClientImpl() { 96 // Make sure to kill the PairingConnection before terminating the fdevent 97 // looper. 98 if (connection_ != nullptr) { 99 connection_.reset(); 100 } 101 } 102 103 bool PairingClientImpl::Start(std::string_view ip_addr, pairing_client_result_cb cb, void* opaque) { 104 CHECK(!ip_addr.empty()); 105 cb_ = cb; 106 opaque_ = opaque; 107 108 if (state_ != State::Ready) { 109 LOG(ERROR) << "PairingClient already running or finished"; 110 return false; 111 } 112 113 // Try to parse the host address 114 std::string err; 115 CHECK(android::base::ParseNetAddress(std::string(ip_addr), &host_, &port_, nullptr, &err)); 116 CHECK(port_ > 0 && port_ <= 65535); 117 118 if (!StartConnection()) { 119 LOG(ERROR) << "Unable to start PairingClient connection"; 120 state_ = State::Stopped; 121 return false; 122 } 123 124 state_ = State::Running; 125 return true; 126 } 127 128 bool PairingClientImpl::StartConnection() { 129 std::string err; 130 const int timeout = 10; // seconds 131 unique_fd fd(network_connect(host_, port_, SOCK_STREAM, timeout, &err)); 132 if (fd.get() == -1) { 133 LOG(ERROR) << "Failed to start pairing connection client [" << err << "]"; 134 return false; 135 } 136 int off = 1; 137 adb_setsockopt(fd.get(), IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off)); 138 139 connection_ = ConnectionPtr( 140 pairing_connection_client_new(pswd_.data(), pswd_.size(), &peer_info_, cert_.data(), 141 cert_.size(), priv_key_.data(), priv_key_.size())); 142 CHECK(connection_); 143 144 int osh = cast_handle_to_int(adb_get_os_handle(fd.release())); 145 if (!pairing_connection_start(connection_.get(), osh, OnPairingResult, this)) { 146 LOG(ERROR) << "PairingClient failed to start the PairingConnection"; 147 state_ = State::Stopped; 148 return false; 149 } 150 151 return true; 152 } 153 154 // static 155 void PairingClientImpl::OnPairingResult(const PeerInfo* peer_info, int /* fd */, void* opaque) { 156 auto* p = reinterpret_cast<PairingClientImpl*>(opaque); 157 p->cb_(peer_info, p->opaque_); 158 } 159 160 } // namespace 161 162 // static 163 std::unique_ptr<PairingClient> PairingClient::Create(const Data& pswd, const PeerInfo& peer_info, 164 const Data& cert, const Data& priv_key) { 165 CHECK(!pswd.empty()); 166 CHECK(!cert.empty()); 167 CHECK(!priv_key.empty()); 168 169 return std::unique_ptr<PairingClient>(new PairingClientImpl(pswd, peer_info, cert, priv_key)); 170 } 171 172 } // namespace pairing 173 } // namespace adbwifi 174