blob: 29df70631648f830864d79477903cacd62d9c4fc [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 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 <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <errno.h>
21#include <string.h>
22#include <ctype.h>
23
24#include "sysdeps.h"
25
jzhuan51297d222013-05-24 17:40:15 -040026#if !ADB_HOST
27#include <cutils/properties.h>
28#endif
29
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030#define TRACE_TAG TRACE_SOCKETS
31#include "adb.h"
32
Josh Gao83cb3032016-06-21 16:28:29 -070033#if defined(__BIONIC__)
34#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
35#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036
Josh Gao83cb3032016-06-21 16:28:29 -070037static pthread_mutex_t socket_list_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080038
39int sendfailmsg(int fd, const char *reason)
40{
41 char buf[9];
42 int len;
43 len = strlen(reason);
44 if(len > 0xffff) len = 0xffff;
45 snprintf(buf, sizeof buf, "FAIL%04x", len);
46 if(writex(fd, buf, 8)) return -1;
47 return writex(fd, reason, len);
48}
49
50//extern int online;
51
52static unsigned local_socket_next_id = 1;
53
54static asocket local_socket_list = {
55 .next = &local_socket_list,
56 .prev = &local_socket_list,
57};
58
59/* the the list of currently closing local sockets.
60** these have no peer anymore, but still packets to
61** write to their fd.
62*/
63static asocket local_socket_closing_list = {
64 .next = &local_socket_closing_list,
65 .prev = &local_socket_closing_list,
66};
67
David 'Digit' Turner818d6412013-12-13 14:09:44 +010068// Parse the global list of sockets to find one with id |local_id|.
69// If |peer_id| is not 0, also check that it is connected to a peer
70// with id |peer_id|. Returns an asocket handle on success, NULL on failure.
71asocket *find_local_socket(unsigned local_id, unsigned peer_id)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080072{
73 asocket *s;
74 asocket *result = NULL;
75
Josh Gao83cb3032016-06-21 16:28:29 -070076 pthread_mutex_lock(&socket_list_lock);
André Goddard Rosa81828292010-06-12 11:40:20 -030077 for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
David 'Digit' Turner818d6412013-12-13 14:09:44 +010078 if (s->id != local_id)
79 continue;
80 if (peer_id == 0 || (s->peer && s->peer->id == peer_id)) {
André Goddard Rosa81828292010-06-12 11:40:20 -030081 result = s;
André Goddard Rosa81828292010-06-12 11:40:20 -030082 }
David 'Digit' Turner818d6412013-12-13 14:09:44 +010083 break;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080084 }
Josh Gao83cb3032016-06-21 16:28:29 -070085 pthread_mutex_unlock(&socket_list_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080086
87 return result;
88}
89
90static void
91insert_local_socket(asocket* s, asocket* list)
92{
93 s->next = list;
94 s->prev = s->next->prev;
95 s->prev->next = s;
96 s->next->prev = s;
97}
98
99
100void install_local_socket(asocket *s)
101{
Josh Gao83cb3032016-06-21 16:28:29 -0700102 pthread_mutex_lock(&socket_list_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103
104 s->id = local_socket_next_id++;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100105
106 // Socket ids should never be 0.
107 if (local_socket_next_id == 0)
108 local_socket_next_id = 1;
109
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800110 insert_local_socket(s, &local_socket_list);
111
Josh Gao83cb3032016-06-21 16:28:29 -0700112 pthread_mutex_unlock(&socket_list_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113}
114
115void remove_socket(asocket *s)
116{
117 // socket_list_lock should already be held
118 if (s->prev && s->next)
119 {
120 s->prev->next = s->next;
121 s->next->prev = s->prev;
122 s->next = 0;
123 s->prev = 0;
124 s->id = 0;
125 }
126}
127
128void close_all_sockets(atransport *t)
129{
130 asocket *s;
131
132 /* this is a little gross, but since s->close() *will* modify
133 ** the list out from under you, your options are limited.
134 */
Josh Gao83cb3032016-06-21 16:28:29 -0700135 pthread_mutex_lock(&socket_list_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800136restart:
137 for(s = local_socket_list.next; s != &local_socket_list; s = s->next){
138 if(s->transport == t || (s->peer && s->peer->transport == t)) {
Josh Gao83cb3032016-06-21 16:28:29 -0700139 s->close(s);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800140 goto restart;
141 }
142 }
Josh Gao83cb3032016-06-21 16:28:29 -0700143 pthread_mutex_unlock(&socket_list_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800144}
145
146static int local_socket_enqueue(asocket *s, apacket *p)
147{
148 D("LS(%d): enqueue %d\n", s->id, p->len);
149
150 p->ptr = p->data;
151
152 /* if there is already data queue'd, we will receive
153 ** events when it's time to write. just add this to
154 ** the tail
155 */
156 if(s->pkt_first) {
157 goto enqueue;
158 }
159
160 /* write as much as we can, until we
161 ** would block or there is an error/eof
162 */
163 while(p->len > 0) {
164 int r = adb_write(s->fd, p->ptr, p->len);
165 if(r > 0) {
166 p->len -= r;
167 p->ptr += r;
168 continue;
169 }
170 if((r == 0) || (errno != EAGAIN)) {
171 D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) );
172 s->close(s);
173 return 1; /* not ready (error) */
174 } else {
175 break;
176 }
177 }
178
179 if(p->len == 0) {
180 put_apacket(p);
181 return 0; /* ready for more data */
182 }
183
184enqueue:
185 p->next = 0;
186 if(s->pkt_first) {
187 s->pkt_last->next = p;
188 } else {
189 s->pkt_first = p;
190 }
191 s->pkt_last = p;
192
193 /* make sure we are notified when we can drain the queue */
194 fdevent_add(&s->fde, FDE_WRITE);
195
196 return 1; /* not ready (backlog) */
197}
198
199static void local_socket_ready(asocket *s)
200{
201 /* far side is ready for data, pay attention to
202 readable events */
203 fdevent_add(&s->fde, FDE_READ);
204// D("LS(%d): ready()\n", s->id);
205}
206
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800207// be sure to hold the socket list lock when calling this
208static void local_socket_destroy(asocket *s)
209{
210 apacket *p, *n;
Benoit Gobyf366b362012-03-16 14:50:07 -0700211 int exit_on_close = s->exit_on_close;
212
JP Abgrall408fa572011-03-16 15:57:42 -0700213 D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800214
215 /* IMPORTANT: the remove closes the fd
216 ** that belongs to this socket
217 */
218 fdevent_remove(&s->fde);
219
220 /* dispose of any unwritten data */
221 for(p = s->pkt_first; p; p = n) {
222 D("LS(%d): discarding %d bytes\n", s->id, p->len);
223 n = p->next;
224 put_apacket(p);
225 }
226 remove_socket(s);
227 free(s);
Benoit Gobyf366b362012-03-16 14:50:07 -0700228
229 if (exit_on_close) {
230 D("local_socket_destroy: exiting\n");
231 exit(1);
232 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800233}
234
235
Josh Gao83cb3032016-06-21 16:28:29 -0700236static void local_socket_close(asocket *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800237{
Josh Gao83cb3032016-06-21 16:28:29 -0700238 pthread_mutex_lock(&socket_list_lock);
JP Abgrall408fa572011-03-16 15:57:42 -0700239 D("entered. LS(%d) fd=%d\n", s->id, s->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800240 if(s->peer) {
JP Abgrall408fa572011-03-16 15:57:42 -0700241 D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
242 s->id, s->peer->id, s->peer->fd);
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100243 /* Note: it's important to call shutdown before disconnecting from
244 * the peer, this ensures that remote sockets can still get the id
245 * of the local socket they're connected to, to send a CLOSE()
246 * protocol event. */
247 if (s->peer->shutdown)
248 s->peer->shutdown(s->peer);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800249 s->peer->peer = 0;
Josh Gao83cb3032016-06-21 16:28:29 -0700250 s->peer->close(s->peer);
Tom Marlin49f18572011-05-13 13:24:55 -0500251 s->peer = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800252 }
253
254 /* If we are already closing, or if there are no
255 ** pending packets, destroy immediately
256 */
257 if (s->closing || s->pkt_first == NULL) {
258 int id = s->id;
259 local_socket_destroy(s);
260 D("LS(%d): closed\n", id);
Josh Gao83cb3032016-06-21 16:28:29 -0700261 pthread_mutex_unlock(&socket_list_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262 return;
263 }
264
265 /* otherwise, put on the closing list
266 */
267 D("LS(%d): closing\n", s->id);
268 s->closing = 1;
269 fdevent_del(&s->fde, FDE_READ);
270 remove_socket(s);
JP Abgrall408fa572011-03-16 15:57:42 -0700271 D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800272 insert_local_socket(s, &local_socket_closing_list);
Josh Gao83cb3032016-06-21 16:28:29 -0700273 pthread_mutex_unlock(&socket_list_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800274}
275
276static void local_socket_event_func(int fd, unsigned ev, void *_s)
277{
278 asocket *s = _s;
279
JP Abgrall408fa572011-03-16 15:57:42 -0700280 D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);
281
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800282 /* put the FDE_WRITE processing before the FDE_READ
283 ** in order to simplify the code.
284 */
285 if(ev & FDE_WRITE){
286 apacket *p;
287
288 while((p = s->pkt_first) != 0) {
289 while(p->len > 0) {
290 int r = adb_write(fd, p->ptr, p->len);
291 if(r > 0) {
292 p->ptr += r;
293 p->len -= r;
294 continue;
295 }
296 if(r < 0) {
297 /* returning here is ok because FDE_READ will
298 ** be processed in the next iteration loop
299 */
300 if(errno == EAGAIN) return;
301 if(errno == EINTR) continue;
302 }
Christopher Tate5b811fa2011-06-10 11:38:37 -0700303 D(" closing after write because r=%d and errno is %d\n", r, errno);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800304 s->close(s);
305 return;
306 }
307
308 if(p->len == 0) {
309 s->pkt_first = p->next;
310 if(s->pkt_first == 0) s->pkt_last = 0;
311 put_apacket(p);
312 }
313 }
314
315 /* if we sent the last packet of a closing socket,
316 ** we can now destroy it.
317 */
318 if (s->closing) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700319 D(" closing because 'closing' is set after write\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800320 s->close(s);
321 return;
322 }
323
324 /* no more packets queued, so we can ignore
325 ** writable events again and tell our peer
326 ** to resume writing
327 */
328 fdevent_del(&s->fde, FDE_WRITE);
329 s->peer->ready(s->peer);
330 }
331
332
333 if(ev & FDE_READ){
334 apacket *p = get_apacket();
335 unsigned char *x = p->data;
336 size_t avail = MAX_PAYLOAD;
337 int r;
338 int is_eof = 0;
339
340 while(avail > 0) {
341 r = adb_read(fd, x, avail);
Elliott Hughesccecf142014-01-16 10:53:11 -0800342 D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n", s->id, s->fd, r, r<0?errno:0, avail);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800343 if(r > 0) {
344 avail -= r;
345 x += r;
346 continue;
347 }
348 if(r < 0) {
349 if(errno == EAGAIN) break;
350 if(errno == EINTR) continue;
351 }
352
353 /* r = 0 or unhandled error */
354 is_eof = 1;
355 break;
356 }
JP Abgrall408fa572011-03-16 15:57:42 -0700357 D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n",
358 s->id, s->fd, r, is_eof, s->fde.force_eof);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800359 if((avail == MAX_PAYLOAD) || (s->peer == 0)) {
360 put_apacket(p);
361 } else {
362 p->len = MAX_PAYLOAD - avail;
363
364 r = s->peer->enqueue(s->peer, p);
JP Abgrall408fa572011-03-16 15:57:42 -0700365 D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800366
367 if(r < 0) {
368 /* error return means they closed us as a side-effect
369 ** and we must return immediately.
370 **
371 ** note that if we still have buffered packets, the
372 ** socket will be placed on the closing socket list.
373 ** this handler function will be called again
374 ** to process FDE_WRITE events.
375 */
376 return;
377 }
378
379 if(r > 0) {
380 /* if the remote cannot accept further events,
381 ** we disable notification of READs. They'll
382 ** be enabled again when we get a call to ready()
383 */
384 fdevent_del(&s->fde, FDE_READ);
385 }
386 }
JP Abgrall112445b2011-04-12 22:01:58 -0700387 /* Don't allow a forced eof if data is still there */
388 if((s->fde.force_eof && !r) || is_eof) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700389 D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800390 s->close(s);
391 }
392 }
393
394 if(ev & FDE_ERROR){
395 /* this should be caught be the next read or write
396 ** catching it here means we may skip the last few
397 ** bytes of readable data.
398 */
399// s->close(s);
JP Abgrall408fa572011-03-16 15:57:42 -0700400 D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
401
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800402 return;
403 }
404}
405
406asocket *create_local_socket(int fd)
407{
408 asocket *s = calloc(1, sizeof(asocket));
André Goddard Rosac419e2a2010-06-10 20:48:19 -0300409 if (s == NULL) fatal("cannot allocate socket");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 s->fd = fd;
411 s->enqueue = local_socket_enqueue;
412 s->ready = local_socket_ready;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100413 s->shutdown = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414 s->close = local_socket_close;
JP Abgrall408fa572011-03-16 15:57:42 -0700415 install_local_socket(s);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800416
417 fdevent_install(&s->fde, fd, local_socket_event_func, s);
418/* fdevent_add(&s->fde, FDE_ERROR); */
419 //fprintf(stderr, "Created local socket in create_local_socket \n");
420 D("LS(%d): created (fd=%d)\n", s->id, s->fd);
421 return s;
422}
423
424asocket *create_local_service_socket(const char *name)
425{
426 asocket *s;
427 int fd;
jzhuan51297d222013-05-24 17:40:15 -0400428#if !ADB_HOST
429 char debug[PROPERTY_VALUE_MAX];
430#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800431
432#if !ADB_HOST
433 if (!strcmp(name,"jdwp")) {
434 return create_jdwp_service_socket();
435 }
436 if (!strcmp(name,"track-jdwp")) {
437 return create_jdwp_tracker_service_socket();
438 }
439#endif
440 fd = service_to_fd(name);
441 if(fd < 0) return 0;
442
443 s = create_local_socket(fd);
JP Abgrall408fa572011-03-16 15:57:42 -0700444 D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
Benoit Gobyf366b362012-03-16 14:50:07 -0700445
JP Abgrallf91259a2012-03-30 13:19:11 -0700446#if !ADB_HOST
jzhuan51297d222013-05-24 17:40:15 -0400447 if (!strncmp(name, "root:", 5))
448 property_get("ro.debuggable", debug, "");
449
450 if ((!strncmp(name, "root:", 5) && getuid() != 0
451 && strcmp(debug, "1") == 0)
Benoit Gobyaeceb512012-06-12 12:12:18 -0700452 || !strncmp(name, "usb:", 4)
453 || !strncmp(name, "tcpip:", 6)) {
Benoit Gobyf366b362012-03-16 14:50:07 -0700454 D("LS(%d): enabling exit_on_close\n", s->id);
455 s->exit_on_close = 1;
456 }
JP Abgrallf91259a2012-03-30 13:19:11 -0700457#endif
Benoit Gobyf366b362012-03-16 14:50:07 -0700458
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800459 return s;
460}
461
462#if ADB_HOST
463static asocket *create_host_service_socket(const char *name, const char* serial)
464{
465 asocket *s;
466
467 s = host_service_to_socket(name, serial);
468
469 if (s != NULL) {
470 D("LS(%d) bound to '%s'\n", s->id, name);
471 return s;
472 }
473
474 return s;
475}
476#endif /* ADB_HOST */
477
478/* a Remote socket is used to send/receive data to/from a given transport object
479** it needs to be closed when the transport is forcibly destroyed by the user
480*/
481typedef struct aremotesocket {
482 asocket socket;
483 adisconnect disconnect;
484} aremotesocket;
485
486static int remote_socket_enqueue(asocket *s, apacket *p)
487{
JP Abgrall408fa572011-03-16 15:57:42 -0700488 D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n",
489 s->id, s->fd, s->peer->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800490 p->msg.command = A_WRTE;
491 p->msg.arg0 = s->peer->id;
492 p->msg.arg1 = s->id;
493 p->msg.data_length = p->len;
494 send_packet(p, s->transport);
495 return 1;
496}
497
498static void remote_socket_ready(asocket *s)
499{
JP Abgrall408fa572011-03-16 15:57:42 -0700500 D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n",
501 s->id, s->fd, s->peer->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800502 apacket *p = get_apacket();
503 p->msg.command = A_OKAY;
504 p->msg.arg0 = s->peer->id;
505 p->msg.arg1 = s->id;
506 send_packet(p, s->transport);
507}
508
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100509static void remote_socket_shutdown(asocket *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800510{
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100511 D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d\n",
JP Abgrall408fa572011-03-16 15:57:42 -0700512 s->id, s->fd, s->peer?s->peer->fd:-1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800513 apacket *p = get_apacket();
514 p->msg.command = A_CLSE;
515 if(s->peer) {
516 p->msg.arg0 = s->peer->id;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100517 }
518 p->msg.arg1 = s->id;
519 send_packet(p, s->transport);
520}
521
522static void remote_socket_close(asocket *s)
523{
524 if (s->peer) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800525 s->peer->peer = 0;
JP Abgrall408fa572011-03-16 15:57:42 -0700526 D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n",
527 s->id, s->peer->id, s->peer->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800528 s->peer->close(s->peer);
529 }
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100530 D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n",
531 s->id, s->fd, s->peer?s->peer->fd:-1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800532 D("RS(%d): closed\n", s->id);
533 remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
534 free(s);
535}
536
537static void remote_socket_disconnect(void* _s, atransport* t)
538{
539 asocket* s = _s;
540 asocket* peer = s->peer;
541
542 D("remote_socket_disconnect RS(%d)\n", s->id);
543 if (peer) {
544 peer->peer = NULL;
545 peer->close(peer);
546 }
547 remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
548 free(s);
549}
550
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100551/* Create an asocket to exchange packets with a remote service through transport
552 |t|. Where |id| is the socket id of the corresponding service on the other
553 side of the transport (it is allocated by the remote side and _cannot_ be 0).
554 Returns a new non-NULL asocket handle. */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800555asocket *create_remote_socket(unsigned id, atransport *t)
556{
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100557 asocket* s;
558 adisconnect* dis;
559
560 if (id == 0) fatal("invalid remote socket id (0)");
561 s = calloc(1, sizeof(aremotesocket));
562 dis = &((aremotesocket*)s)->disconnect;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800563
André Goddard Rosac419e2a2010-06-10 20:48:19 -0300564 if (s == NULL) fatal("cannot allocate socket");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800565 s->id = id;
566 s->enqueue = remote_socket_enqueue;
567 s->ready = remote_socket_ready;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100568 s->shutdown = remote_socket_shutdown;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800569 s->close = remote_socket_close;
570 s->transport = t;
571
572 dis->func = remote_socket_disconnect;
573 dis->opaque = s;
574 add_transport_disconnect( t, dis );
575 D("RS(%d): created\n", s->id);
576 return s;
577}
578
579void connect_to_remote(asocket *s, const char *destination)
580{
JP Abgrall408fa572011-03-16 15:57:42 -0700581 D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800582 apacket *p = get_apacket();
583 int len = strlen(destination) + 1;
584
585 if(len > (MAX_PAYLOAD-1)) {
586 fatal("destination oversized");
587 }
588
589 D("LS(%d): connect('%s')\n", s->id, destination);
590 p->msg.command = A_OPEN;
591 p->msg.arg0 = s->id;
592 p->msg.data_length = len;
593 strcpy((char*) p->data, destination);
594 send_packet(p, s->transport);
595}
596
597
598/* this is used by magic sockets to rig local sockets to
599 send the go-ahead message when they connect */
600static void local_socket_ready_notify(asocket *s)
601{
602 s->ready = local_socket_ready;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100603 s->shutdown = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800604 s->close = local_socket_close;
605 adb_write(s->fd, "OKAY", 4);
606 s->ready(s);
607}
608
609/* this is used by magic sockets to rig local sockets to
610 send the failure message if they are closed before
611 connected (to avoid closing them without a status message) */
612static void local_socket_close_notify(asocket *s)
613{
614 s->ready = local_socket_ready;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100615 s->shutdown = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800616 s->close = local_socket_close;
617 sendfailmsg(s->fd, "closed");
618 s->close(s);
619}
620
621unsigned unhex(unsigned char *s, int len)
622{
623 unsigned n = 0, c;
624
625 while(len-- > 0) {
626 switch((c = *s++)) {
627 case '0': case '1': case '2':
628 case '3': case '4': case '5':
629 case '6': case '7': case '8':
630 case '9':
631 c -= '0';
632 break;
633 case 'a': case 'b': case 'c':
634 case 'd': case 'e': case 'f':
635 c = c - 'a' + 10;
636 break;
637 case 'A': case 'B': case 'C':
638 case 'D': case 'E': case 'F':
639 c = c - 'A' + 10;
640 break;
641 default:
642 return 0xffffffff;
643 }
644
645 n = (n << 4) | c;
646 }
647
648 return n;
649}
650
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700651#define PREFIX(str) { str, sizeof(str) - 1 }
652static const struct prefix_struct {
653 const char *str;
654 const size_t len;
655} prefixes[] = {
656 PREFIX("usb:"),
657 PREFIX("product:"),
658 PREFIX("model:"),
659 PREFIX("device:"),
660};
661static const int num_prefixes = (sizeof(prefixes) / sizeof(prefixes[0]));
662
Terence Haddock28e13902011-03-16 09:43:56 +0100663/* skip_host_serial return the position in a string
664 skipping over the 'serial' parameter in the ADB protocol,
665 where parameter string may be a host:port string containing
666 the protocol delimiter (colon). */
667char *skip_host_serial(char *service) {
668 char *first_colon, *serial_end;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700669 int i;
Terence Haddock28e13902011-03-16 09:43:56 +0100670
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700671 for (i = 0; i < num_prefixes; i++) {
672 if (!strncmp(service, prefixes[i].str, prefixes[i].len))
673 return strchr(service + prefixes[i].len, ':');
Scott Anderson3608d832012-05-31 12:04:23 -0700674 }
675
Terence Haddock28e13902011-03-16 09:43:56 +0100676 first_colon = strchr(service, ':');
677 if (!first_colon) {
678 /* No colon in service string. */
679 return NULL;
680 }
681 serial_end = first_colon;
682 if (isdigit(serial_end[1])) {
683 serial_end++;
684 while ((*serial_end) && isdigit(*serial_end)) {
685 serial_end++;
686 }
687 if ((*serial_end) != ':') {
688 // Something other than numbers was found, reset the end.
689 serial_end = first_colon;
690 }
691 }
692 return serial_end;
693}
694
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800695static int smart_socket_enqueue(asocket *s, apacket *p)
696{
697 unsigned len;
698#if ADB_HOST
699 char *service = NULL;
700 char* serial = NULL;
701 transport_type ttype = kTransportAny;
702#endif
703
704 D("SS(%d): enqueue %d\n", s->id, p->len);
705
706 if(s->pkt_first == 0) {
707 s->pkt_first = p;
708 s->pkt_last = p;
709 } else {
710 if((s->pkt_first->len + p->len) > MAX_PAYLOAD) {
711 D("SS(%d): overflow\n", s->id);
712 put_apacket(p);
713 goto fail;
714 }
715
716 memcpy(s->pkt_first->data + s->pkt_first->len,
717 p->data, p->len);
718 s->pkt_first->len += p->len;
719 put_apacket(p);
720
721 p = s->pkt_first;
722 }
723
724 /* don't bother if we can't decode the length */
725 if(p->len < 4) return 0;
726
727 len = unhex(p->data, 4);
728 if((len < 1) || (len > 1024)) {
729 D("SS(%d): bad size (%d)\n", s->id, len);
730 goto fail;
731 }
732
733 D("SS(%d): len is %d\n", s->id, len );
734 /* can't do anything until we have the full header */
735 if((len + 4) > p->len) {
736 D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len);
737 return 0;
738 }
739
740 p->data[len + 4] = 0;
741
742 D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4));
743
744#if ADB_HOST
745 service = (char *)p->data + 4;
746 if(!strncmp(service, "host-serial:", strlen("host-serial:"))) {
747 char* serial_end;
748 service += strlen("host-serial:");
749
Terence Haddock28e13902011-03-16 09:43:56 +0100750 // serial number should follow "host:" and could be a host:port string.
751 serial_end = skip_host_serial(service);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800752 if (serial_end) {
753 *serial_end = 0; // terminate string
754 serial = service;
755 service = serial_end + 1;
756 }
757 } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
758 ttype = kTransportUsb;
759 service += strlen("host-usb:");
760 } else if (!strncmp(service, "host-local:", strlen("host-local:"))) {
761 ttype = kTransportLocal;
762 service += strlen("host-local:");
763 } else if (!strncmp(service, "host:", strlen("host:"))) {
764 ttype = kTransportAny;
765 service += strlen("host:");
766 } else {
767 service = NULL;
768 }
769
770 if (service) {
771 asocket *s2;
772
773 /* some requests are handled immediately -- in that
774 ** case the handle_host_request() routine has sent
775 ** the OKAY or FAIL message and all we have to do
776 ** is clean up.
777 */
778 if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) {
779 /* XXX fail message? */
780 D( "SS(%d): handled host service '%s'\n", s->id, service );
781 goto fail;
782 }
783 if (!strncmp(service, "transport", strlen("transport"))) {
784 D( "SS(%d): okay transport\n", s->id );
785 p->len = 0;
786 return 0;
787 }
788
789 /* try to find a local service with this name.
790 ** if no such service exists, we'll fail out
791 ** and tear down here.
792 */
793 s2 = create_host_service_socket(service, serial);
794 if(s2 == 0) {
795 D( "SS(%d): couldn't create host service '%s'\n", s->id, service );
796 sendfailmsg(s->peer->fd, "unknown host service");
797 goto fail;
798 }
799
800 /* we've connected to a local host service,
801 ** so we make our peer back into a regular
802 ** local socket and bind it to the new local
803 ** service socket, acknowledge the successful
804 ** connection, and close this smart socket now
805 ** that its work is done.
806 */
807 adb_write(s->peer->fd, "OKAY", 4);
808
809 s->peer->ready = local_socket_ready;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100810 s->peer->shutdown = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800811 s->peer->close = local_socket_close;
812 s->peer->peer = s2;
813 s2->peer = s->peer;
814 s->peer = 0;
815 D( "SS(%d): okay\n", s->id );
816 s->close(s);
817
818 /* initial state is "ready" */
819 s2->ready(s2);
820 return 0;
821 }
822#else /* !ADB_HOST */
823 if (s->transport == NULL) {
824 char* error_string = "unknown failure";
825 s->transport = acquire_one_transport (CS_ANY,
826 kTransportAny, NULL, &error_string);
827
828 if (s->transport == NULL) {
829 sendfailmsg(s->peer->fd, error_string);
830 goto fail;
831 }
832 }
833#endif
834
835 if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) {
836 /* if there's no remote we fail the connection
837 ** right here and terminate it
838 */
839 sendfailmsg(s->peer->fd, "device offline (x)");
840 goto fail;
841 }
842
843
844 /* instrument our peer to pass the success or fail
845 ** message back once it connects or closes, then
846 ** detach from it, request the connection, and
847 ** tear down
848 */
849 s->peer->ready = local_socket_ready_notify;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100850 s->peer->shutdown = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800851 s->peer->close = local_socket_close_notify;
852 s->peer->peer = 0;
853 /* give him our transport and upref it */
854 s->peer->transport = s->transport;
855
856 connect_to_remote(s->peer, (char*) (p->data + 4));
857 s->peer = 0;
858 s->close(s);
859 return 1;
860
861fail:
862 /* we're going to close our peer as a side-effect, so
863 ** return -1 to signal that state to the local socket
864 ** who is enqueueing against us
865 */
866 s->close(s);
867 return -1;
868}
869
870static void smart_socket_ready(asocket *s)
871{
872 D("SS(%d): ready\n", s->id);
873}
874
875static void smart_socket_close(asocket *s)
876{
877 D("SS(%d): closed\n", s->id);
878 if(s->pkt_first){
879 put_apacket(s->pkt_first);
880 }
881 if(s->peer) {
882 s->peer->peer = 0;
883 s->peer->close(s->peer);
Tom Marlin49f18572011-05-13 13:24:55 -0500884 s->peer = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800885 }
886 free(s);
887}
888
Benoit Goby9470c2f2013-02-20 15:04:53 -0800889static asocket *create_smart_socket(void)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800890{
891 D("Creating smart socket \n");
892 asocket *s = calloc(1, sizeof(asocket));
André Goddard Rosac419e2a2010-06-10 20:48:19 -0300893 if (s == NULL) fatal("cannot allocate socket");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800894 s->enqueue = smart_socket_enqueue;
895 s->ready = smart_socket_ready;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100896 s->shutdown = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800897 s->close = smart_socket_close;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800898
Benoit Goby9470c2f2013-02-20 15:04:53 -0800899 D("SS(%d)\n", s->id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800900 return s;
901}
902
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800903void connect_to_smartsocket(asocket *s)
904{
905 D("Connecting to smart socket \n");
Benoit Goby9470c2f2013-02-20 15:04:53 -0800906 asocket *ss = create_smart_socket();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800907 s->peer = ss;
908 ss->peer = s;
909 s->ready(s);
910}