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 "host/frontend/webrtc/adb_handler.h"
18 
19 #include <unistd.h>
20 
21 #include <https/BaseConnection.h>
22 #include <https/Support.h>
23 
24 #include <android-base/logging.h>
25 
26 using namespace android;
27 
28 namespace cuttlefish {
29 namespace webrtc_streaming {
30 
31 struct AdbHandler::AdbConnection : public BaseConnection {
32   explicit AdbConnection(AdbHandler *parent, std::shared_ptr<RunLoop> runLoop,
33                          int sock);
34 
35   void send(const void *_data, size_t size);
36 
37  protected:
38   long processClientRequest(const void *data, size_t size) override;
39   void onDisconnect(int err) override;
40 
41  private:
42   AdbHandler *mParent;
43 };
44 
45 ////////////////////////////////////////////////////////////////////////////////
46 
AdbConnection(AdbHandler * parent,std::shared_ptr<RunLoop> runLoop,int sock)47 AdbHandler::AdbConnection::AdbConnection(AdbHandler *parent,
48                                          std::shared_ptr<RunLoop> runLoop,
49                                          int sock)
50     : BaseConnection(runLoop, sock), mParent(parent) {}
51 
processClientRequest(const void * _data,size_t size)52 long AdbHandler::AdbConnection::processClientRequest(const void *_data,
53                                                      size_t size) {
54   auto data = static_cast<const uint8_t *>(_data);
55 
56   LOG(VERBOSE) << "AdbConnection::processClientRequest (size = " << size << ")";
57 
58   LOG(VERBOSE) << hexdump(data, size);
59 
60   mParent->send_to_client_(data, size);
61   return size;
62 }
63 
onDisconnect(int err)64 void AdbHandler::AdbConnection::onDisconnect(int err) {
65   LOG(VERBOSE) << "AdbConnection::onDisconnect(err=" << err << ")";
66 
67   mParent->send_to_client_(nullptr /* data */, 0 /* size */);
68 }
69 
send(const void * _data,size_t size)70 void AdbHandler::AdbConnection::send(const void *_data, size_t size) {
71   BaseConnection::send(_data, size);
72 }
73 
74 ////////////////////////////////////////////////////////////////////////////////
75 
AdbHandler(std::shared_ptr<RunLoop> runLoop,const std::string & adb_host_and_port,std::function<void (const uint8_t *,size_t)> send_to_client)76 AdbHandler::AdbHandler(
77     std::shared_ptr<RunLoop> runLoop, const std::string &adb_host_and_port,
78     std::function<void(const uint8_t *, size_t)> send_to_client)
79     : mRunLoop(runLoop), mSocket(-1), send_to_client_(send_to_client) {
80   LOG(VERBOSE) << "Connecting to " << adb_host_and_port;
81 
82   auto err = setupSocket(adb_host_and_port);
83   CHECK(!err);
84 
85   mAdbConnection = std::make_shared<AdbConnection>(this, mRunLoop, mSocket);
86 }
87 
~AdbHandler()88 AdbHandler::~AdbHandler() {
89   if (mSocket >= 0) {
90     close(mSocket);
91     mSocket = -1;
92   }
93 }
94 
run()95 void AdbHandler::run() { mAdbConnection->run(); }
96 
setupSocket(const std::string & adb_host_and_port)97 int AdbHandler::setupSocket(const std::string &adb_host_and_port) {
98   auto colonPos = adb_host_and_port.find(':');
99   if (colonPos == std::string::npos) {
100     return -EINVAL;
101   }
102 
103   auto host = adb_host_and_port.substr(0, colonPos);
104 
105   const char *portString = adb_host_and_port.c_str() + colonPos + 1;
106   char *end;
107   unsigned long port = strtoul(portString, &end, 10);
108 
109   if (end == portString || *end != '\0' || port > 65535) {
110     return -EINVAL;
111   }
112 
113   int err;
114 
115   int sock = socket(PF_INET, SOCK_STREAM, 0);
116 
117   if (sock < 0) {
118     err = -errno;
119     goto bail;
120   }
121 
122   makeFdNonblocking(sock);
123 
124   sockaddr_in addr;
125   memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
126   addr.sin_family = AF_INET;
127   addr.sin_addr.s_addr = inet_addr(host.c_str());
128   addr.sin_port = htons(port);
129 
130   if (connect(sock, reinterpret_cast<const sockaddr *>(&addr), sizeof(addr)) <
131           0 &&
132       errno != EINPROGRESS) {
133     err = -errno;
134     goto bail2;
135   }
136 
137   mSocket = sock;
138 
139   return 0;
140 
141 bail2:
142   close(sock);
143   sock = -1;
144 
145 bail:
146   return err;
147 }
148 
handleMessage(const uint8_t * msg,size_t len)149 void AdbHandler::handleMessage(const uint8_t *msg, size_t len) {
150   LOG(VERBOSE) << hexdump(msg, len);
151 
152   mAdbConnection->send(msg, len);
153 }
154 
155 }  // namespace webrtc_streaming
156 }  // namespace cuttlefish
157