1 /* 2 * Copyright (C) 2015 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 "adb_listeners.h" 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 22 #include <algorithm> 23 #include <list> 24 25 #include <android-base/stringprintf.h> 26 #include <android-base/strings.h> 27 #include <android-base/thread_annotations.h> 28 #include <cutils/sockets.h> 29 30 #include "socket_spec.h" 31 #include "sysdeps.h" 32 #include "sysdeps/memory.h" 33 #include "transport.h" 34 35 // A listener is an entity which binds to a local port and, upon receiving a connection on that 36 // port, creates an asocket to connect the new local connection to a specific remote service. 37 // 38 // TODO: some listeners read from the new connection to determine what exact service to connect to 39 // on the far side. 40 class alistener { 41 public: 42 alistener(const std::string& _local_name, const std::string& _connect_to); 43 ~alistener(); 44 45 fdevent fde; 46 int fd = -1; 47 48 std::string local_name; 49 std::string connect_to; 50 atransport* transport = nullptr; 51 adisconnect disconnect; 52 53 private: 54 DISALLOW_COPY_AND_ASSIGN(alistener); 55 }; 56 57 alistener::alistener(const std::string& _local_name, const std::string& _connect_to) 58 : local_name(_local_name), connect_to(_connect_to) { 59 } 60 61 alistener::~alistener() { 62 // Closes the corresponding fd. 63 fdevent_remove(&fde); 64 65 if (transport) { 66 transport->RemoveDisconnect(&disconnect); 67 } 68 } 69 70 // listener_list retains ownership of all created alistener objects. Removing an alistener from 71 // this list will cause it to be deleted. 72 static auto& listener_list_mutex = *new std::mutex(); 73 typedef std::list<std::unique_ptr<alistener>> ListenerList; 74 static ListenerList& listener_list GUARDED_BY(listener_list_mutex) = *new ListenerList(); 75 76 static void ss_listener_event_func(int _fd, unsigned ev, void *_l) { 77 if (ev & FDE_READ) { 78 int fd = adb_socket_accept(_fd, nullptr, nullptr); 79 if (fd < 0) return; 80 81 int rcv_buf_size = CHUNK_SIZE; 82 adb_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_buf_size, sizeof(rcv_buf_size)); 83 84 asocket* s = create_local_socket(fd); 85 if (s) { 86 connect_to_smartsocket(s); 87 return; 88 } 89 90 adb_close(fd); 91 } 92 } 93 94 static void listener_event_func(int _fd, unsigned ev, void* _l) 95 { 96 alistener* listener = reinterpret_cast<alistener*>(_l); 97 asocket *s; 98 99 if (ev & FDE_READ) { 100 int fd = adb_socket_accept(_fd, nullptr, nullptr); 101 if (fd < 0) { 102 return; 103 } 104 105 s = create_local_socket(fd); 106 if (s) { 107 s->transport = listener->transport; 108 connect_to_remote(s, listener->connect_to.c_str()); 109 return; 110 } 111 112 adb_close(fd); 113 } 114 } 115 116 // Called as a transport disconnect function. |arg| is the raw alistener*. 117 static void listener_disconnect(void* arg, atransport*) EXCLUDES(listener_list_mutex) { 118 std::lock_guard<std::mutex> lock(listener_list_mutex); 119 for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) { 120 if (iter->get() == arg) { 121 (*iter)->transport = nullptr; 122 listener_list.erase(iter); 123 return; 124 } 125 } 126 } 127 128 // Write the list of current listeners (network redirections) into a string. 129 std::string format_listeners() EXCLUDES(listener_list_mutex) { 130 std::lock_guard<std::mutex> lock(listener_list_mutex); 131 std::string result; 132 for (auto& l : listener_list) { 133 // Ignore special listeners like those for *smartsocket* 134 if (l->connect_to[0] == '*') { 135 continue; 136 } 137 // <device-serial> " " <local-name> " " <remote-name> "\n" 138 // Entries from "adb reverse" have no serial. 139 android::base::StringAppendF(&result, "%s %s %s\n", 140 l->transport->serial ? l->transport->serial : "(reverse)", 141 l->local_name.c_str(), l->connect_to.c_str()); 142 } 143 return result; 144 } 145 146 InstallStatus remove_listener(const char* local_name, atransport* transport) 147 EXCLUDES(listener_list_mutex) { 148 std::lock_guard<std::mutex> lock(listener_list_mutex); 149 for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) { 150 if (local_name == (*iter)->local_name) { 151 listener_list.erase(iter); 152 return INSTALL_STATUS_OK; 153 } 154 } 155 return INSTALL_STATUS_LISTENER_NOT_FOUND; 156 } 157 158 void remove_all_listeners() EXCLUDES(listener_list_mutex) { 159 std::lock_guard<std::mutex> lock(listener_list_mutex); 160 auto iter = listener_list.begin(); 161 while (iter != listener_list.end()) { 162 // Never remove smart sockets. 163 if ((*iter)->connect_to[0] == '*') { 164 ++iter; 165 } else { 166 iter = listener_list.erase(iter); 167 } 168 } 169 } 170 171 void close_smartsockets() EXCLUDES(listener_list_mutex) { 172 std::lock_guard<std::mutex> lock(listener_list_mutex); 173 auto pred = [](const std::unique_ptr<alistener>& listener) { 174 return listener->local_name == "*smartsocket*"; 175 }; 176 listener_list.remove_if(pred); 177 } 178 179 InstallStatus install_listener(const std::string& local_name, const char* connect_to, 180 atransport* transport, int no_rebind, int* resolved_tcp_port, 181 std::string* error) EXCLUDES(listener_list_mutex) { 182 std::lock_guard<std::mutex> lock(listener_list_mutex); 183 for (auto& l : listener_list) { 184 if (local_name == l->local_name) { 185 // Can't repurpose a smartsocket. 186 if(l->connect_to[0] == '*') { 187 *error = "cannot repurpose smartsocket"; 188 return INSTALL_STATUS_INTERNAL_ERROR; 189 } 190 191 // Can't repurpose a listener if 'no_rebind' is true. 192 if (no_rebind) { 193 *error = "cannot rebind"; 194 return INSTALL_STATUS_CANNOT_REBIND; 195 } 196 197 l->connect_to = connect_to; 198 if (l->transport != transport) { 199 l->transport->RemoveDisconnect(&l->disconnect); 200 l->transport = transport; 201 l->transport->AddDisconnect(&l->disconnect); 202 } 203 return INSTALL_STATUS_OK; 204 } 205 } 206 207 auto listener = std::make_unique<alistener>(local_name, connect_to); 208 209 int resolved = 0; 210 listener->fd = socket_spec_listen(listener->local_name, error, &resolved); 211 if (listener->fd < 0) { 212 return INSTALL_STATUS_CANNOT_BIND; 213 } 214 215 // If the caller requested port 0, update the listener name with the resolved port. 216 if (resolved != 0) { 217 listener->local_name = android::base::StringPrintf("tcp:%d", resolved); 218 if (resolved_tcp_port) { 219 *resolved_tcp_port = resolved; 220 } 221 } 222 223 close_on_exec(listener->fd); 224 if (listener->connect_to == "*smartsocket*") { 225 fdevent_install(&listener->fde, listener->fd, ss_listener_event_func, listener.get()); 226 } else { 227 fdevent_install(&listener->fde, listener->fd, listener_event_func, listener.get()); 228 } 229 fdevent_set(&listener->fde, FDE_READ); 230 231 listener->transport = transport; 232 233 if (transport) { 234 listener->disconnect.opaque = listener.get(); 235 listener->disconnect.func = listener_disconnect; 236 transport->AddDisconnect(&listener->disconnect); 237 } 238 239 listener_list.push_back(std::move(listener)); 240 return INSTALL_STATUS_OK; 241 } 242