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