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