blob: a335eeced6efbb56089ffd0ce2589a041aaa8ba5 [file] [log] [blame]
Dan Albert020292b2015-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 Albert357bd492015-02-20 17:20:09 -080019#include <stdio.h>
Elliott Hughes1679e922015-02-24 12:37:13 -080020#include <stdlib.h>
Dan Albert357bd492015-02-20 17:20:09 -080021
Elliott Hughes88b4c852015-04-30 17:32:03 -070022#include <base/stringprintf.h>
23
Dan Albert020292b2015-02-18 18:03:26 -080024#include "sysdeps.h"
Dan Albertb302d122015-02-24 15:51:19 -080025#include "transport.h"
Dan Albert020292b2015-02-18 18:03:26 -080026
27int gListenAll = 0; /* Not static because it is used in commandline.c. */
28
Elliott Hughesd98ca8a2015-05-29 17:55:19 -070029static alistener listener_list = {
Dan Albert020292b2015-02-18 18:03:26 -080030 .next = &listener_list,
31 .prev = &listener_list,
32};
33
Elliott Hughesd98ca8a2015-05-29 17:55:19 -070034static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
Dan Albert020292b2015-02-18 18:03:26 -080035 asocket *s;
36
37 if(ev & FDE_READ) {
38 struct sockaddr addr;
39 socklen_t alen;
40 int fd;
41
42 alen = sizeof(addr);
43 fd = adb_socket_accept(_fd, &addr, &alen);
44 if(fd < 0) return;
45
46 adb_socket_setbufsize(fd, CHUNK_SIZE);
47
48 s = create_local_socket(fd);
49 if(s) {
50 connect_to_smartsocket(s);
51 return;
52 }
53
54 adb_close(fd);
55 }
56}
57
Elliott Hughesd98ca8a2015-05-29 17:55:19 -070058static void listener_event_func(int _fd, unsigned ev, void* _l)
Dan Albert020292b2015-02-18 18:03:26 -080059{
Dan Albertf30d73c2015-02-25 17:51:28 -080060 alistener* listener = reinterpret_cast<alistener*>(_l);
Dan Albert020292b2015-02-18 18:03:26 -080061 asocket *s;
62
Dan Albertf30d73c2015-02-25 17:51:28 -080063 if (ev & FDE_READ) {
Dan Albert020292b2015-02-18 18:03:26 -080064 struct sockaddr addr;
65 socklen_t alen;
66 int fd;
67
68 alen = sizeof(addr);
69 fd = adb_socket_accept(_fd, &addr, &alen);
Dan Albertf30d73c2015-02-25 17:51:28 -080070 if (fd < 0) {
71 return;
72 }
Dan Albert020292b2015-02-18 18:03:26 -080073
74 s = create_local_socket(fd);
Dan Albertf30d73c2015-02-25 17:51:28 -080075 if (s) {
76 s->transport = listener->transport;
77 connect_to_remote(s, listener->connect_to);
Dan Albert020292b2015-02-18 18:03:26 -080078 return;
79 }
80
81 adb_close(fd);
82 }
83}
84
85static void free_listener(alistener* l)
86{
87 if (l->next) {
88 l->next->prev = l->prev;
89 l->prev->next = l->next;
90 l->next = l->prev = l;
91 }
92
93 // closes the corresponding fd
94 fdevent_remove(&l->fde);
95
96 if (l->local_name)
97 free((char*)l->local_name);
98
99 if (l->connect_to)
100 free((char*)l->connect_to);
101
102 if (l->transport) {
103 remove_transport_disconnect(l->transport, &l->disconnect);
104 }
105 free(l);
106}
107
Elliott Hughesd98ca8a2015-05-29 17:55:19 -0700108static void listener_disconnect(void* listener, atransport* t) {
Dan Albertf30d73c2015-02-25 17:51:28 -0800109 free_listener(reinterpret_cast<alistener*>(listener));
Dan Albert020292b2015-02-18 18:03:26 -0800110}
111
Elliott Hughesd98ca8a2015-05-29 17:55:19 -0700112static int local_name_to_fd(const char* name) {
113 if (!strncmp("tcp:", name, 4)) {
114 int port = atoi(name + 4);
Dan Albert020292b2015-02-18 18:03:26 -0800115 if (gListenAll > 0) {
Elliott Hughesd98ca8a2015-05-29 17:55:19 -0700116 return socket_inaddr_any_server(port, SOCK_STREAM);
Dan Albert020292b2015-02-18 18:03:26 -0800117 } else {
Elliott Hughesd98ca8a2015-05-29 17:55:19 -0700118 return socket_loopback_server(port, SOCK_STREAM);
Dan Albert020292b2015-02-18 18:03:26 -0800119 }
Dan Albert020292b2015-02-18 18:03:26 -0800120 }
121#ifndef HAVE_WIN32_IPC /* no Unix-domain sockets on Win32 */
Elliott Hughesd98ca8a2015-05-29 17:55:19 -0700122 // It's nonsensical to support the "reserved" space on the adb host side
123 if (!strncmp(name, "local:", 6)) {
124 return socket_local_server(name + 6, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
125 } else if (!strncmp(name, "localabstract:", 14)) {
126 return socket_local_server(name + 14, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
127 } else if (!strncmp(name, "localfilesystem:", 16)) {
128 return socket_local_server(name + 16, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
Dan Albert020292b2015-02-18 18:03:26 -0800129 }
130
131#endif
132 printf("unknown local portname '%s'\n", name);
133 return -1;
134}
135
Elliott Hughes88b4c852015-04-30 17:32:03 -0700136// Write the list of current listeners (network redirections) into a string.
137std::string format_listeners() {
138 std::string result;
139 for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
Dan Albert020292b2015-02-18 18:03:26 -0800140 // Ignore special listeners like those for *smartsocket*
Elliott Hughes88b4c852015-04-30 17:32:03 -0700141 if (l->connect_to[0] == '*') {
142 continue;
Dan Albert020292b2015-02-18 18:03:26 -0800143 }
Elliott Hughes88b4c852015-04-30 17:32:03 -0700144 // <device-serial> " " <local-name> " " <remote-name> "\n"
145 android::base::StringAppendF(&result, "%s %s %s\n",
146 l->transport->serial, l->local_name, l->connect_to);
Dan Albert020292b2015-02-18 18:03:26 -0800147 }
148 return result;
149}
150
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700151InstallStatus remove_listener(const char *local_name, atransport* transport) {
Dan Albert020292b2015-02-18 18:03:26 -0800152 alistener *l;
153
154 for (l = listener_list.next; l != &listener_list; l = l->next) {
155 if (!strcmp(local_name, l->local_name)) {
156 listener_disconnect(l, l->transport);
Elliott Hughesa585cbd2015-04-20 08:09:20 -0700157 return INSTALL_STATUS_OK;
Dan Albert020292b2015-02-18 18:03:26 -0800158 }
159 }
Elliott Hughesa585cbd2015-04-20 08:09:20 -0700160 return INSTALL_STATUS_LISTENER_NOT_FOUND;
Dan Albert020292b2015-02-18 18:03:26 -0800161}
162
163void remove_all_listeners(void)
164{
165 alistener *l, *l_next;
166 for (l = listener_list.next; l != &listener_list; l = l_next) {
167 l_next = l->next;
168 // Never remove smart sockets.
169 if (l->connect_to[0] == '*')
170 continue;
171 listener_disconnect(l, l->transport);
172 }
173}
174
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700175InstallStatus install_listener(const std::string& local_name,
Dan Albert020292b2015-02-18 18:03:26 -0800176 const char *connect_to,
177 atransport* transport,
178 int no_rebind)
179{
Dan Albertf30d73c2015-02-25 17:51:28 -0800180 for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
Elliott Hughesfb596842015-05-01 17:04:38 -0700181 if (local_name == l->local_name) {
Dan Albertf30d73c2015-02-25 17:51:28 -0800182 char* cto;
Dan Albert020292b2015-02-18 18:03:26 -0800183
Dan Albertf30d73c2015-02-25 17:51:28 -0800184 /* can't repurpose a smartsocket */
Dan Albert020292b2015-02-18 18:03:26 -0800185 if(l->connect_to[0] == '*') {
186 return INSTALL_STATUS_INTERNAL_ERROR;
187 }
188
Dan Albertf30d73c2015-02-25 17:51:28 -0800189 /* can't repurpose a listener if 'no_rebind' is true */
Dan Albert020292b2015-02-18 18:03:26 -0800190 if (no_rebind) {
191 return INSTALL_STATUS_CANNOT_REBIND;
192 }
193
194 cto = strdup(connect_to);
195 if(cto == 0) {
196 return INSTALL_STATUS_INTERNAL_ERROR;
197 }
198
Dan Albert020292b2015-02-18 18:03:26 -0800199 free((void*) l->connect_to);
200 l->connect_to = cto;
201 if (l->transport != transport) {
202 remove_transport_disconnect(l->transport, &l->disconnect);
203 l->transport = transport;
204 add_transport_disconnect(l->transport, &l->disconnect);
205 }
206 return INSTALL_STATUS_OK;
207 }
208 }
209
Dan Albertf30d73c2015-02-25 17:51:28 -0800210 alistener* listener = reinterpret_cast<alistener*>(
211 calloc(1, sizeof(alistener)));
212 if (listener == nullptr) {
213 goto nomem;
214 }
Dan Albert020292b2015-02-18 18:03:26 -0800215
Elliott Hughesfb596842015-05-01 17:04:38 -0700216 listener->local_name = strdup(local_name.c_str());
Dan Albertf30d73c2015-02-25 17:51:28 -0800217 if (listener->local_name == nullptr) {
218 goto nomem;
219 }
Dan Albert020292b2015-02-18 18:03:26 -0800220
Dan Albertf30d73c2015-02-25 17:51:28 -0800221 listener->connect_to = strdup(connect_to);
222 if (listener->connect_to == nullptr) {
223 goto nomem;
224 }
225
Elliott Hughesfb596842015-05-01 17:04:38 -0700226 listener->fd = local_name_to_fd(listener->local_name);
Dan Albertf30d73c2015-02-25 17:51:28 -0800227 if (listener->fd < 0) {
Elliott Hughesfb596842015-05-01 17:04:38 -0700228 printf("cannot bind '%s': %s\n", listener->local_name, strerror(errno));
Dan Albertf30d73c2015-02-25 17:51:28 -0800229 free(listener->local_name);
230 free(listener->connect_to);
231 free(listener);
Dan Albertf30d73c2015-02-25 17:51:28 -0800232 return INSTALL_STATUS_CANNOT_BIND;
Dan Albert020292b2015-02-18 18:03:26 -0800233 }
234
Dan Albertf30d73c2015-02-25 17:51:28 -0800235 close_on_exec(listener->fd);
236 if (!strcmp(listener->connect_to, "*smartsocket*")) {
237 fdevent_install(&listener->fde, listener->fd, ss_listener_event_func,
238 listener);
Dan Albert020292b2015-02-18 18:03:26 -0800239 } else {
Dan Albertf30d73c2015-02-25 17:51:28 -0800240 fdevent_install(&listener->fde, listener->fd, listener_event_func,
241 listener);
Dan Albert020292b2015-02-18 18:03:26 -0800242 }
Dan Albertf30d73c2015-02-25 17:51:28 -0800243 fdevent_set(&listener->fde, FDE_READ);
Dan Albert020292b2015-02-18 18:03:26 -0800244
Dan Albertf30d73c2015-02-25 17:51:28 -0800245 listener->next = &listener_list;
246 listener->prev = listener_list.prev;
247 listener->next->prev = listener;
248 listener->prev->next = listener;
249 listener->transport = transport;
Dan Albert020292b2015-02-18 18:03:26 -0800250
251 if (transport) {
Dan Albertf30d73c2015-02-25 17:51:28 -0800252 listener->disconnect.opaque = listener;
253 listener->disconnect.func = listener_disconnect;
254 add_transport_disconnect(transport, &listener->disconnect);
Dan Albert020292b2015-02-18 18:03:26 -0800255 }
256 return INSTALL_STATUS_OK;
257
258nomem:
259 fatal("cannot allocate listener");
260 return INSTALL_STATUS_INTERNAL_ERROR;
261}