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 <android-base/logging.h> 22 23 using namespace android; 24 25 namespace cuttlefish { 26 namespace webrtc_streaming { 27 28 namespace { 29 SetupAdbSocket(const std::string & adb_host_and_port)30 SharedFD SetupAdbSocket(const std::string &adb_host_and_port) { 31 auto colonPos = adb_host_and_port.find(':'); 32 if (colonPos == std::string::npos) { 33 return SharedFD(); 34 } 35 36 auto host = adb_host_and_port.substr(0, colonPos); 37 38 const char *portString = adb_host_and_port.c_str() + colonPos + 1; 39 char *end; 40 unsigned long port = strtoul(portString, &end, 10); 41 42 if (end == portString || *end != '\0' || port > 65535) { 43 return SharedFD(); 44 } 45 46 auto local_client = SharedFD::SocketLocalClient(port, SOCK_STREAM); 47 if (!local_client->IsOpen()) { 48 LOG(WARNING) << "Failed to connect to ADB server socket (non-Android guest?) Using /dev/null workaround." 49 << local_client->StrError(); 50 return SharedFD::Open("/dev/null", O_RDWR); 51 } 52 return local_client; 53 } 54 55 } // namespace 56 AdbHandler(const std::string & adb_host_and_port,std::function<void (const uint8_t *,size_t)> send_to_client)57 AdbHandler::AdbHandler( 58 const std::string &adb_host_and_port, 59 std::function<void(const uint8_t *, size_t)> send_to_client) 60 : send_to_client_(send_to_client), 61 adb_socket_(SetupAdbSocket(adb_host_and_port)), 62 shutdown_(SharedFD::Event(0,0)) 63 { 64 std::thread loop([this]() { ReadLoop(); }); 65 read_thread_.swap(loop); 66 } 67 68 ~AdbHandler()69 AdbHandler::~AdbHandler() { 70 // Send a message to the looper to shut down. 71 uint64_t v = 1; 72 shutdown_->Write(&v, sizeof(v)); 73 // Shut down the socket as well. Not srictly necessary. 74 adb_socket_->Shutdown(SHUT_RDWR); 75 read_thread_.join(); 76 } 77 ReadLoop()78 void AdbHandler::ReadLoop() { 79 while (1) { 80 uint8_t buffer[4096]; 81 82 read_set_.Set(shutdown_); 83 read_set_.Set(adb_socket_); 84 Select(&read_set_, nullptr, nullptr, nullptr); 85 86 if (read_set_.IsSet(adb_socket_)) { 87 auto read = adb_socket_->Read(buffer, sizeof(buffer)); 88 if (read < 0) { 89 LOG(ERROR) << "Error on reading from ADB socket: " << strerror(adb_socket_->GetErrno()); 90 break; 91 } 92 if (read) { 93 send_to_client_(buffer, read); 94 } 95 } 96 97 if (read_set_.IsSet(shutdown_)) { 98 LOG(INFO) << "AdbHandler is shutting down."; 99 break; 100 } 101 } 102 } 103 handleMessage(const uint8_t * msg,size_t len)104 void AdbHandler::handleMessage(const uint8_t *msg, size_t len) { 105 size_t sent = 0; 106 while (sent < len) { 107 auto this_sent = adb_socket_->Write(&msg[sent], len - sent); 108 if (this_sent < 0) { 109 LOG(ERROR) << "Error writing to adb socket: " << adb_socket_->StrError(); 110 return; 111 } 112 sent += this_sent; 113 } 114 } 115 116 } // namespace webrtc_streaming 117 } // namespace cuttlefish 118