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