blob: a1a5ddb52d3aa17f8cad4a96eeb3f6dbf7cadce6 [file] [log] [blame]
Dan Alberte9fca142015-02-18 18:03:26 -08001/*
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
Dan Albertbf106472015-02-20 17:20:09 -080019#include <stdio.h>
Elliott Hughes3b967f52015-02-24 12:37:13 -080020#include <stdlib.h>
Dan Albertbf106472015-02-20 17:20:09 -080021
Dan Alberte9fca142015-02-18 18:03:26 -080022#include "sysdeps.h"
Dan Albert76649012015-02-24 15:51:19 -080023#include "transport.h"
Dan Alberte9fca142015-02-18 18:03:26 -080024
25int gListenAll = 0; /* Not static because it is used in commandline.c. */
26
27alistener listener_list = {
28 .next = &listener_list,
29 .prev = &listener_list,
30};
31
32void ss_listener_event_func(int _fd, unsigned ev, void *_l)
33{
34 asocket *s;
35
36 if(ev & FDE_READ) {
37 struct sockaddr addr;
38 socklen_t alen;
39 int fd;
40
41 alen = sizeof(addr);
42 fd = adb_socket_accept(_fd, &addr, &alen);
43 if(fd < 0) return;
44
45 adb_socket_setbufsize(fd, CHUNK_SIZE);
46
47 s = create_local_socket(fd);
48 if(s) {
49 connect_to_smartsocket(s);
50 return;
51 }
52
53 adb_close(fd);
54 }
55}
56
Dan Albertbac34742015-02-25 17:51:28 -080057void listener_event_func(int _fd, unsigned ev, void* _l)
Dan Alberte9fca142015-02-18 18:03:26 -080058{
Dan Albertbac34742015-02-25 17:51:28 -080059 alistener* listener = reinterpret_cast<alistener*>(_l);
Dan Alberte9fca142015-02-18 18:03:26 -080060 asocket *s;
61
Dan Albertbac34742015-02-25 17:51:28 -080062 if (ev & FDE_READ) {
Dan Alberte9fca142015-02-18 18:03:26 -080063 struct sockaddr addr;
64 socklen_t alen;
65 int fd;
66
67 alen = sizeof(addr);
68 fd = adb_socket_accept(_fd, &addr, &alen);
Dan Albertbac34742015-02-25 17:51:28 -080069 if (fd < 0) {
70 return;
71 }
Dan Alberte9fca142015-02-18 18:03:26 -080072
73 s = create_local_socket(fd);
Dan Albertbac34742015-02-25 17:51:28 -080074 if (s) {
75 s->transport = listener->transport;
76 connect_to_remote(s, listener->connect_to);
Dan Alberte9fca142015-02-18 18:03:26 -080077 return;
78 }
79
80 adb_close(fd);
81 }
82}
83
84static void free_listener(alistener* l)
85{
86 if (l->next) {
87 l->next->prev = l->prev;
88 l->prev->next = l->next;
89 l->next = l->prev = l;
90 }
91
92 // closes the corresponding fd
93 fdevent_remove(&l->fde);
94
95 if (l->local_name)
96 free((char*)l->local_name);
97
98 if (l->connect_to)
99 free((char*)l->connect_to);
100
101 if (l->transport) {
102 remove_transport_disconnect(l->transport, &l->disconnect);
103 }
104 free(l);
105}
106
Dan Albertbac34742015-02-25 17:51:28 -0800107void listener_disconnect(void* listener, atransport* t)
Dan Alberte9fca142015-02-18 18:03:26 -0800108{
Dan Albertbac34742015-02-25 17:51:28 -0800109 free_listener(reinterpret_cast<alistener*>(listener));
Dan Alberte9fca142015-02-18 18:03:26 -0800110}
111
112int local_name_to_fd(const char *name)
113{
114 int port;
115
116 if(!strncmp("tcp:", name, 4)){
117 int ret;
118 port = atoi(name + 4);
119
120 if (gListenAll > 0) {
121 ret = socket_inaddr_any_server(port, SOCK_STREAM);
122 } else {
123 ret = socket_loopback_server(port, SOCK_STREAM);
124 }
125
126 return ret;
127 }
128#ifndef HAVE_WIN32_IPC /* no Unix-domain sockets on Win32 */
129 // It's non-sensical to support the "reserved" space on the adb host side
130 if(!strncmp(name, "local:", 6)) {
131 return socket_local_server(name + 6,
132 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
133 } else if(!strncmp(name, "localabstract:", 14)) {
134 return socket_local_server(name + 14,
135 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
136 } else if(!strncmp(name, "localfilesystem:", 16)) {
137 return socket_local_server(name + 16,
138 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
139 }
140
141#endif
142 printf("unknown local portname '%s'\n", name);
143 return -1;
144}
145
146// Write a single line describing a listener to a user-provided buffer.
147// Appends a trailing zero, even in case of truncation, but the function
148// returns the full line length.
149// If |buffer| is NULL, does not write but returns required size.
150static int format_listener(alistener* l, char* buffer, size_t buffer_len) {
151 // Format is simply:
152 //
153 // <device-serial> " " <local-name> " " <remote-name> "\n"
154 //
155 int local_len = strlen(l->local_name);
156 int connect_len = strlen(l->connect_to);
157 int serial_len = strlen(l->transport->serial);
158
159 if (buffer != NULL) {
160 snprintf(buffer, buffer_len, "%s %s %s\n",
161 l->transport->serial, l->local_name, l->connect_to);
162 }
163 // NOTE: snprintf() on Windows returns -1 in case of truncation, so
164 // return the computed line length instead.
165 return local_len + connect_len + serial_len + 3;
166}
167
168// Write the list of current listeners (network redirections) into a
169// user-provided buffer. Appends a trailing zero, even in case of
170// trunctaion, but return the full size in bytes.
171// If |buffer| is NULL, does not write but returns required size.
172int format_listeners(char* buf, size_t buflen)
173{
174 alistener* l;
175 int result = 0;
176 for (l = listener_list.next; l != &listener_list; l = l->next) {
177 // Ignore special listeners like those for *smartsocket*
178 if (l->connect_to[0] == '*')
179 continue;
180 int len = format_listener(l, buf, buflen);
181 // Ensure there is space for the trailing zero.
182 result += len;
183 if (buf != NULL) {
184 buf += len;
185 buflen -= len;
186 if (buflen <= 0)
187 break;
188 }
189 }
190 return result;
191}
192
Elliott Hughes7b506092015-04-20 08:09:20 -0700193install_status_t remove_listener(const char *local_name, atransport* transport)
Dan Alberte9fca142015-02-18 18:03:26 -0800194{
195 alistener *l;
196
197 for (l = listener_list.next; l != &listener_list; l = l->next) {
198 if (!strcmp(local_name, l->local_name)) {
199 listener_disconnect(l, l->transport);
Elliott Hughes7b506092015-04-20 08:09:20 -0700200 return INSTALL_STATUS_OK;
Dan Alberte9fca142015-02-18 18:03:26 -0800201 }
202 }
Elliott Hughes7b506092015-04-20 08:09:20 -0700203 return INSTALL_STATUS_LISTENER_NOT_FOUND;
Dan Alberte9fca142015-02-18 18:03:26 -0800204}
205
206void remove_all_listeners(void)
207{
208 alistener *l, *l_next;
209 for (l = listener_list.next; l != &listener_list; l = l_next) {
210 l_next = l->next;
211 // Never remove smart sockets.
212 if (l->connect_to[0] == '*')
213 continue;
214 listener_disconnect(l, l->transport);
215 }
216}
217
218install_status_t install_listener(const char *local_name,
219 const char *connect_to,
220 atransport* transport,
221 int no_rebind)
222{
Dan Albertbac34742015-02-25 17:51:28 -0800223 for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
224 if (strcmp(local_name, l->local_name) == 0) {
225 char* cto;
Dan Alberte9fca142015-02-18 18:03:26 -0800226
Dan Albertbac34742015-02-25 17:51:28 -0800227 /* can't repurpose a smartsocket */
Dan Alberte9fca142015-02-18 18:03:26 -0800228 if(l->connect_to[0] == '*') {
229 return INSTALL_STATUS_INTERNAL_ERROR;
230 }
231
Dan Albertbac34742015-02-25 17:51:28 -0800232 /* can't repurpose a listener if 'no_rebind' is true */
Dan Alberte9fca142015-02-18 18:03:26 -0800233 if (no_rebind) {
234 return INSTALL_STATUS_CANNOT_REBIND;
235 }
236
237 cto = strdup(connect_to);
238 if(cto == 0) {
239 return INSTALL_STATUS_INTERNAL_ERROR;
240 }
241
Dan Alberte9fca142015-02-18 18:03:26 -0800242 free((void*) l->connect_to);
243 l->connect_to = cto;
244 if (l->transport != transport) {
245 remove_transport_disconnect(l->transport, &l->disconnect);
246 l->transport = transport;
247 add_transport_disconnect(l->transport, &l->disconnect);
248 }
249 return INSTALL_STATUS_OK;
250 }
251 }
252
Dan Albertbac34742015-02-25 17:51:28 -0800253 alistener* listener = reinterpret_cast<alistener*>(
254 calloc(1, sizeof(alistener)));
255 if (listener == nullptr) {
256 goto nomem;
257 }
Dan Alberte9fca142015-02-18 18:03:26 -0800258
Dan Albertbac34742015-02-25 17:51:28 -0800259 listener->local_name = strdup(local_name);
260 if (listener->local_name == nullptr) {
261 goto nomem;
262 }
Dan Alberte9fca142015-02-18 18:03:26 -0800263
Dan Albertbac34742015-02-25 17:51:28 -0800264 listener->connect_to = strdup(connect_to);
265 if (listener->connect_to == nullptr) {
266 goto nomem;
267 }
268
269 listener->fd = local_name_to_fd(local_name);
270 if (listener->fd < 0) {
Elliott Hughes7b506092015-04-20 08:09:20 -0700271 printf("cannot bind '%s': %s\n", local_name, strerror(errno));
Dan Albertbac34742015-02-25 17:51:28 -0800272 free(listener->local_name);
273 free(listener->connect_to);
274 free(listener);
Dan Albertbac34742015-02-25 17:51:28 -0800275 return INSTALL_STATUS_CANNOT_BIND;
Dan Alberte9fca142015-02-18 18:03:26 -0800276 }
277
Dan Albertbac34742015-02-25 17:51:28 -0800278 close_on_exec(listener->fd);
279 if (!strcmp(listener->connect_to, "*smartsocket*")) {
280 fdevent_install(&listener->fde, listener->fd, ss_listener_event_func,
281 listener);
Dan Alberte9fca142015-02-18 18:03:26 -0800282 } else {
Dan Albertbac34742015-02-25 17:51:28 -0800283 fdevent_install(&listener->fde, listener->fd, listener_event_func,
284 listener);
Dan Alberte9fca142015-02-18 18:03:26 -0800285 }
Dan Albertbac34742015-02-25 17:51:28 -0800286 fdevent_set(&listener->fde, FDE_READ);
Dan Alberte9fca142015-02-18 18:03:26 -0800287
Dan Albertbac34742015-02-25 17:51:28 -0800288 listener->next = &listener_list;
289 listener->prev = listener_list.prev;
290 listener->next->prev = listener;
291 listener->prev->next = listener;
292 listener->transport = transport;
Dan Alberte9fca142015-02-18 18:03:26 -0800293
294 if (transport) {
Dan Albertbac34742015-02-25 17:51:28 -0800295 listener->disconnect.opaque = listener;
296 listener->disconnect.func = listener_disconnect;
297 add_transport_disconnect(transport, &listener->disconnect);
Dan Alberte9fca142015-02-18 18:03:26 -0800298 }
299 return INSTALL_STATUS_OK;
300
301nomem:
302 fatal("cannot allocate listener");
303 return INSTALL_STATUS_INTERNAL_ERROR;
304}