1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cui#define TRACE_TAG SOCKETS
183313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
193313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "sysdeps.h"
203313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
217664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <ctype.h>
227664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <errno.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
267664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <unistd.h>
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low#include <algorithm>
29268068f25673242d1d5130d96202d3288c91b700Josh Gao#include <mutex>
30802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell#include <string>
31802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell#include <vector>
32363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low
337664901a355b959f312e9acff5a0fd31b7139623Dan Albert#if !ADB_HOST
347664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include "cutils/properties.h"
357664901a355b959f312e9acff5a0fd31b7139623Dan Albert#endif
363313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
373313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "adb.h"
383313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "adb_io.h"
39268068f25673242d1d5130d96202d3288c91b700Josh Gao#include "sysdeps/mutex.h"
407664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include "transport.h"
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
42268068f25673242d1d5130d96202d3288c91b700Josh Gaostatic std::recursive_mutex& local_socket_list_lock = *new std::recursive_mutex();
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic unsigned local_socket_next_id = 1;
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic asocket local_socket_list = {
4663760409ad833cf803482e098367f49741b5f6d3Josh Gao    .next = &local_socket_list, .prev = &local_socket_list,
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* the the list of currently closing local sockets.
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** these have no peer anymore, but still packets to
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** write to their fd.
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic asocket local_socket_closing_list = {
5463760409ad833cf803482e098367f49741b5f6d3Josh Gao    .next = &local_socket_closing_list, .prev = &local_socket_closing_list,
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner// Parse the global list of sockets to find one with id |local_id|.
58818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner// If |peer_id| is not 0, also check that it is connected to a peer
59818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner// with id |peer_id|. Returns an asocket handle on success, NULL on failure.
6063760409ad833cf803482e098367f49741b5f6d3Josh Gaoasocket* find_local_socket(unsigned local_id, unsigned peer_id) {
6163760409ad833cf803482e098367f49741b5f6d3Josh Gao    asocket* s;
6263760409ad833cf803482e098367f49741b5f6d3Josh Gao    asocket* result = NULL;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
64268068f25673242d1d5130d96202d3288c91b700Josh Gao    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
658182829ccb46fc5b043ea258672602dc2928dee2André Goddard Rosa    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
6663760409ad833cf803482e098367f49741b5f6d3Josh Gao        if (s->id != local_id) {
67818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner            continue;
6863760409ad833cf803482e098367f49741b5f6d3Josh Gao        }
69818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        if (peer_id == 0 || (s->peer && s->peer->id == peer_id)) {
708182829ccb46fc5b043ea258672602dc2928dee2André Goddard Rosa            result = s;
718182829ccb46fc5b043ea258672602dc2928dee2André Goddard Rosa        }
72818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        break;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
7863760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void insert_local_socket(asocket* s, asocket* list) {
7963760409ad833cf803482e098367f49741b5f6d3Josh Gao    s->next = list;
8063760409ad833cf803482e098367f49741b5f6d3Josh Gao    s->prev = s->next->prev;
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->prev->next = s;
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->next->prev = s;
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8563760409ad833cf803482e098367f49741b5f6d3Josh Gaovoid install_local_socket(asocket* s) {
86268068f25673242d1d5130d96202d3288c91b700Josh Gao    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->id = local_socket_next_id++;
89818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner
90818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    // Socket ids should never be 0.
9163760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (local_socket_next_id == 0) {
92268068f25673242d1d5130d96202d3288c91b700Josh Gao        fatal("local socket id overflow");
9363760409ad833cf803482e098367f49741b5f6d3Josh Gao    }
94818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    insert_local_socket(s, &local_socket_list);
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
9863760409ad833cf803482e098367f49741b5f6d3Josh Gaovoid remove_socket(asocket* s) {
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // socket_list_lock should already be held
10063760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s->prev && s->next) {
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->prev->next = s->next;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->next->prev = s->prev;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->next = 0;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->prev = 0;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->id = 0;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10963760409ad833cf803482e098367f49741b5f6d3Josh Gaovoid close_all_sockets(atransport* t) {
11063760409ad833cf803482e098367f49741b5f6d3Josh Gao    asocket* s;
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
11263760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* this is a little gross, but since s->close() *will* modify
11363760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** the list out from under you, your options are limited.
11463760409ad833cf803482e098367f49741b5f6d3Josh Gao    */
115268068f25673242d1d5130d96202d3288c91b700Josh Gao    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectrestart:
11763760409ad833cf803482e098367f49741b5f6d3Josh Gao    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
11863760409ad833cf803482e098367f49741b5f6d3Josh Gao        if (s->transport == t || (s->peer && s->peer->transport == t)) {
119014b01706cc64dc9c2ad94a96f62e07c058d0b5dJosh Gao            s->close(s);
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto restart;
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
12563760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic int local_socket_enqueue(asocket* s, apacket* p) {
1267a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("LS(%d): enqueue %d", s->id, p->len);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->ptr = p->data;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
13063760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* if there is already data queue'd, we will receive
13163760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** events when it's time to write.  just add this to
13263760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** the tail
13363760409ad833cf803482e098367f49741b5f6d3Josh Gao    */
13463760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s->pkt_first) {
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto enqueue;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
13863760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* write as much as we can, until we
13963760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** would block or there is an error/eof
14063760409ad833cf803482e098367f49741b5f6d3Josh Gao    */
14163760409ad833cf803482e098367f49741b5f6d3Josh Gao    while (p->len > 0) {
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int r = adb_write(s->fd, p->ptr, p->len);
14363760409ad833cf803482e098367f49741b5f6d3Josh Gao        if (r > 0) {
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p->len -= r;
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p->ptr += r;
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
14863760409ad833cf803482e098367f49741b5f6d3Josh Gao        if ((r == 0) || (errno != EAGAIN)) {
14963760409ad833cf803482e098367f49741b5f6d3Josh Gao            D("LS(%d): not ready, errno=%d: %s", s->id, errno, strerror(errno));
150c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin Cui            put_apacket(p);
151c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin Cui            s->has_write_error = true;
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s->close(s);
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 1; /* not ready (error) */
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
15963760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (p->len == 0) {
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(p);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0; /* ready for more data */
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectenqueue:
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->next = 0;
16663760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s->pkt_first) {
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_last->next = p;
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_first = p;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->pkt_last = p;
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17363760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* make sure we are notified when we can drain the queue */
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_add(&s->fde, FDE_WRITE);
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1; /* not ready (backlog) */
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17963760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void local_socket_ready(asocket* s) {
180b627a0e2ed63377c828b1f324dd0120fee4e4cd3Nanik Tolaram    /* far side is ready for data, pay attention to
181b627a0e2ed63377c828b1f324dd0120fee4e4cd3Nanik Tolaram       readable events */
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_add(&s->fde, FDE_READ);
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// be sure to hold the socket list lock when calling this
18663760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void local_socket_destroy(asocket* s) {
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p, *n;
188f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby    int exit_on_close = s->exit_on_close;
189f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby
1907a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("LS(%d): destroying fde.fd=%d", s->id, s->fde.fd);
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19263760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* IMPORTANT: the remove closes the fd
19363760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** that belongs to this socket
19463760409ad833cf803482e098367f49741b5f6d3Josh Gao    */
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_remove(&s->fde);
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19763760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* dispose of any unwritten data */
19863760409ad833cf803482e098367f49741b5f6d3Josh Gao    for (p = s->pkt_first; p; p = n) {
1997a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("LS(%d): discarding %d bytes", s->id, p->len);
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        n = p->next;
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(p);
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_socket(s);
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
205f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby
206f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby    if (exit_on_close) {
2077a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("local_socket_destroy: exiting");
208f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby        exit(1);
209f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby    }
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
212268068f25673242d1d5130d96202d3288c91b700Josh Gaostatic void local_socket_close(asocket* s) {
213268068f25673242d1d5130d96202d3288c91b700Josh Gao    D("entered local_socket_close. LS(%d) fd=%d", s->id, s->fd);
214268068f25673242d1d5130d96202d3288c91b700Josh Gao    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
21563760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s->peer) {
21663760409ad833cf803482e098367f49741b5f6d3Josh Gao        D("LS(%d): closing peer. peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
217818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        /* Note: it's important to call shutdown before disconnecting from
218818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner         * the peer, this ensures that remote sockets can still get the id
219818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner         * of the local socket they're connected to, to send a CLOSE()
220818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner         * protocol event. */
22163760409ad833cf803482e098367f49741b5f6d3Josh Gao        if (s->peer->shutdown) {
22263760409ad833cf803482e098367f49741b5f6d3Josh Gao            s->peer->shutdown(s->peer);
22363760409ad833cf803482e098367f49741b5f6d3Josh Gao        }
224268068f25673242d1d5130d96202d3288c91b700Josh Gao        s->peer->peer = nullptr;
225268068f25673242d1d5130d96202d3288c91b700Josh Gao        s->peer->close(s->peer);
226268068f25673242d1d5130d96202d3288c91b700Josh Gao        s->peer = nullptr;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
22963760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* If we are already closing, or if there are no
23063760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** pending packets, destroy immediately
23163760409ad833cf803482e098367f49741b5f6d3Josh Gao    */
232c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin Cui    if (s->closing || s->has_write_error || s->pkt_first == NULL) {
23363760409ad833cf803482e098367f49741b5f6d3Josh Gao        int id = s->id;
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        local_socket_destroy(s);
2357a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("LS(%d): closed", id);
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
23963760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* otherwise, put on the closing list
24063760409ad833cf803482e098367f49741b5f6d3Josh Gao    */
2417a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("LS(%d): closing", s->id);
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->closing = 1;
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_del(&s->fde, FDE_READ);
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_socket(s);
2457a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("LS(%d): put on socket_closing_list fd=%d", s->id, s->fd);
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    insert_local_socket(s, &local_socket_closing_list);
247c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin Cui    CHECK_EQ(FDE_WRITE, s->fde.state & FDE_WRITE);
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
25063760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void local_socket_event_func(int fd, unsigned ev, void* _s) {
251bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    asocket* s = reinterpret_cast<asocket*>(_s);
2527a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("LS(%d): event_func(fd=%d(==%d), ev=%04x)", s->id, s->fd, fd, ev);
253408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* put the FDE_WRITE processing before the FDE_READ
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ** in order to simplify the code.
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    */
257bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    if (ev & FDE_WRITE) {
258bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        apacket* p;
259bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        while ((p = s->pkt_first) != nullptr) {
260bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert            while (p->len > 0) {
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int r = adb_write(fd, p->ptr, p->len);
262bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                if (r == -1) {
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* returning here is ok because FDE_READ will
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ** be processed in the next iteration loop
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    */
266bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                    if (errno == EAGAIN) {
267bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                        return;
268bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                    }
269bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                } else if (r > 0) {
270bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                    p->ptr += r;
271bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                    p->len -= r;
272bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                    continue;
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
274bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert
2757a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                D(" closing after write because r=%d and errno is %d", r, errno);
276c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin Cui                s->has_write_error = true;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->close(s);
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
281bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert            if (p->len == 0) {
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->pkt_first = p->next;
283bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                if (s->pkt_first == 0) {
284bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                    s->pkt_last = 0;
285bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                }
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                put_apacket(p);
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
290bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        /* if we sent the last packet of a closing socket,
291bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        ** we can now destroy it.
292bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        */
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (s->closing) {
2947a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui            D(" closing because 'closing' is set after write");
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s->close(s);
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
299bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        /* no more packets queued, so we can ignore
300bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        ** writable events again and tell our peer
301bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        ** to resume writing
302bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        */
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_del(&s->fde, FDE_WRITE);
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->ready(s->peer);
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
307bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    if (ev & FDE_READ) {
30863760409ad833cf803482e098367f49741b5f6d3Josh Gao        apacket* p = get_apacket();
30963760409ad833cf803482e098367f49741b5f6d3Josh Gao        unsigned char* x = p->data;
3103d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        const size_t max_payload = s->get_max_payload();
3113d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        size_t avail = max_payload;
3123d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        int r = 0;
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int is_eof = 0;
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
315bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        while (avail > 0) {
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            r = adb_read(fd, x, avail);
31763760409ad833cf803482e098367f49741b5f6d3Josh Gao            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu", s->id, s->fd, r,
31863760409ad833cf803482e098367f49741b5f6d3Josh Gao              r < 0 ? errno : 0, avail);
319bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert            if (r == -1) {
320bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                if (errno == EAGAIN) {
321bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                    break;
322bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert                }
323bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert            } else if (r > 0) {
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                avail -= r;
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                x += r;
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                continue;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
329bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert            /* r = 0 or unhandled error */
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            is_eof = 1;
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
33363760409ad833cf803482e098367f49741b5f6d3Josh Gao        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d", s->id, s->fd, r, is_eof,
33463760409ad833cf803482e098367f49741b5f6d3Josh Gao          s->fde.force_eof);
3353d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        if ((avail == max_payload) || (s->peer == 0)) {
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            put_apacket(p);
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
3383d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer            p->len = max_payload - avail;
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
34000674124213d6a9f0564632a5ad172cbd78caf24Yabin Cui            // s->peer->enqueue() may call s->close() and free s,
34100674124213d6a9f0564632a5ad172cbd78caf24Yabin Cui            // so save variables for debug printing below.
34200674124213d6a9f0564632a5ad172cbd78caf24Yabin Cui            unsigned saved_id = s->id;
34300674124213d6a9f0564632a5ad172cbd78caf24Yabin Cui            int saved_fd = s->fd;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            r = s->peer->enqueue(s->peer, p);
3457a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui            D("LS(%u): fd=%d post peer->enqueue(). r=%d", saved_id, saved_fd, r);
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
347bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert            if (r < 0) {
34863760409ad833cf803482e098367f49741b5f6d3Josh Gao                /* error return means they closed us as a side-effect
34963760409ad833cf803482e098367f49741b5f6d3Josh Gao                ** and we must return immediately.
35063760409ad833cf803482e098367f49741b5f6d3Josh Gao                **
35163760409ad833cf803482e098367f49741b5f6d3Josh Gao                ** note that if we still have buffered packets, the
35263760409ad833cf803482e098367f49741b5f6d3Josh Gao                ** socket will be placed on the closing socket list.
35363760409ad833cf803482e098367f49741b5f6d3Josh Gao                ** this handler function will be called again
35463760409ad833cf803482e098367f49741b5f6d3Josh Gao                ** to process FDE_WRITE events.
35563760409ad833cf803482e098367f49741b5f6d3Josh Gao                */
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
359bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert            if (r > 0) {
36063760409ad833cf803482e098367f49741b5f6d3Josh Gao                /* if the remote cannot accept further events,
36163760409ad833cf803482e098367f49741b5f6d3Josh Gao                ** we disable notification of READs.  They'll
36263760409ad833cf803482e098367f49741b5f6d3Josh Gao                ** be enabled again when we get a call to ready()
36363760409ad833cf803482e098367f49741b5f6d3Josh Gao                */
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fdevent_del(&s->fde, FDE_READ);
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
367112445b8a752ce174f36cf853d5f1c356c3f5286JP Abgrall        /* Don't allow a forced eof if data is still there */
368bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        if ((s->fde.force_eof && !r) || is_eof) {
36963760409ad833cf803482e098367f49741b5f6d3Josh Gao            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d", is_eof, r, s->fde.force_eof);
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s->close(s);
371c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin Cui            return;
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
37563760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (ev & FDE_ERROR) {
37663760409ad833cf803482e098367f49741b5f6d3Josh Gao        /* this should be caught be the next read or write
37763760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** catching it here means we may skip the last few
37863760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** bytes of readable data.
37963760409ad833cf803482e098367f49741b5f6d3Josh Gao        */
3807a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("LS(%d): FDE_ERROR (fd=%d)", s->id, s->fd);
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38563760409ad833cf803482e098367f49741b5f6d3Josh Gaoasocket* create_local_socket(int fd) {
38663760409ad833cf803482e098367f49741b5f6d3Josh Gao    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
38763760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s == NULL) {
38863760409ad833cf803482e098367f49741b5f6d3Josh Gao        fatal("cannot allocate socket");
38963760409ad833cf803482e098367f49741b5f6d3Josh Gao    }
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->fd = fd;
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->enqueue = local_socket_enqueue;
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = local_socket_ready;
393818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    s->shutdown = NULL;
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = local_socket_close;
395408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    install_local_socket(s);
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_install(&s->fde, fd, local_socket_event_func, s);
3987a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("LS(%d): created (fd=%d)", s->id, s->fd);
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
40263760409ad833cf803482e098367f49741b5f6d3Josh Gaoasocket* create_local_service_socket(const char* name, const atransport* transport) {
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if !ADB_HOST
40463760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (!strcmp(name, "jdwp")) {
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return create_jdwp_service_socket();
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
40763760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (!strcmp(name, "track-jdwp")) {
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return create_jdwp_tracker_service_socket();
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
4110955c66b226db7a7f34613f834f7b0a145fd407dDavid Pursell    int fd = service_to_fd(name, transport);
41263760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (fd < 0) {
41363760409ad833cf803482e098367f49741b5f6d3Josh Gao        return 0;
41463760409ad833cf803482e098367f49741b5f6d3Josh Gao    }
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4169885881d0689e7999f2d7e7558e894dc73a0a0b0Dan Pasanen    asocket* s = create_local_socket(fd);
4177a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("LS(%d): bound to '%s' via %d", s->id, name, fd);
418f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby
419f91259a8f0d75d721761d588a4b811427565c984JP Abgrall#if !ADB_HOST
4209885881d0689e7999f2d7e7558e894dc73a0a0b0Dan Pasanen    char debug[PROPERTY_VALUE_MAX];
42163760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (!strncmp(name, "root:", 5)) {
4221297d22bc99c26b2ad414faedd5bea73a16ecb90jzhuan        property_get("ro.debuggable", debug, "");
42363760409ad833cf803482e098367f49741b5f6d3Josh Gao    }
4241297d22bc99c26b2ad414faedd5bea73a16ecb90jzhuan
42563760409ad833cf803482e098367f49741b5f6d3Josh Gao    if ((!strncmp(name, "root:", 5) && getuid() != 0 && strcmp(debug, "1") == 0) ||
42663760409ad833cf803482e098367f49741b5f6d3Josh Gao        (!strncmp(name, "unroot:", 7) && getuid() == 0) ||
42763760409ad833cf803482e098367f49741b5f6d3Josh Gao        !strncmp(name, "usb:", 4) ||
42863760409ad833cf803482e098367f49741b5f6d3Josh Gao        !strncmp(name, "tcpip:", 6)) {
4297a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("LS(%d): enabling exit_on_close", s->id);
430f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby        s->exit_on_close = 1;
431f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby    }
432f91259a8f0d75d721761d588a4b811427565c984JP Abgrall#endif
433f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
43863760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic asocket* create_host_service_socket(const char* name, const char* serial) {
43963760409ad833cf803482e098367f49741b5f6d3Josh Gao    asocket* s;
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s = host_service_to_socket(name, serial);
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s != NULL) {
4447a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("LS(%d) bound to '%s'", s->id, name);
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return s;
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* ADB_HOST */
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45263760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic int remote_socket_enqueue(asocket* s, apacket* p) {
45363760409ad833cf803482e098367f49741b5f6d3Josh Gao    D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_WRTE;
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = s->peer->id;
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = s->id;
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.data_length = p->len;
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46263760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void remote_socket_ready(asocket* s) {
46363760409ad833cf803482e098367f49741b5f6d3Josh Gao    D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
46463760409ad833cf803482e098367f49741b5f6d3Josh Gao    apacket* p = get_apacket();
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_OKAY;
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = s->peer->id;
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = s->id;
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
47163760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void remote_socket_shutdown(asocket* s) {
47263760409ad833cf803482e098367f49741b5f6d3Josh Gao    D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d", s->id, s->fd,
47363760409ad833cf803482e098367f49741b5f6d3Josh Gao      s->peer ? s->peer->fd : -1);
47463760409ad833cf803482e098367f49741b5f6d3Josh Gao    apacket* p = get_apacket();
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_CLSE;
47663760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s->peer) {
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p->msg.arg0 = s->peer->id;
478818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    }
479818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    p->msg.arg1 = s->id;
480818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    send_packet(p, s->transport);
481818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner}
482818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner
48363760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void remote_socket_close(asocket* s) {
484818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    if (s->peer) {
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = 0;
48663760409ad833cf803482e098367f49741b5f6d3Josh Gao        D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->close(s->peer);
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
48963760409ad833cf803482e098367f49741b5f6d3Josh Gao    D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d", s->id, s->fd,
49063760409ad833cf803482e098367f49741b5f6d3Josh Gao      s->peer ? s->peer->fd : -1);
4917a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("RS(%d): closed", s->id);
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
495fd28f327ee0e110208ef42ded829286643860394Yabin Cui// Create a remote socket to exchange packets with a remote service through transport
496fd28f327ee0e110208ef42ded829286643860394Yabin Cui// |t|. Where |id| is the socket id of the corresponding service on the other
497fd28f327ee0e110208ef42ded829286643860394Yabin Cui//  side of the transport (it is allocated by the remote side and _cannot_ be 0).
498fd28f327ee0e110208ef42ded829286643860394Yabin Cui// Returns a new non-NULL asocket handle.
49963760409ad833cf803482e098367f49741b5f6d3Josh Gaoasocket* create_remote_socket(unsigned id, atransport* t) {
50063760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (id == 0) {
50163760409ad833cf803482e098367f49741b5f6d3Josh Gao        fatal("invalid remote socket id (0)");
50263760409ad833cf803482e098367f49741b5f6d3Josh Gao    }
503fd28f327ee0e110208ef42ded829286643860394Yabin Cui    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50563760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s == NULL) {
50663760409ad833cf803482e098367f49741b5f6d3Josh Gao        fatal("cannot allocate socket");
50763760409ad833cf803482e098367f49741b5f6d3Josh Gao    }
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->id = id;
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->enqueue = remote_socket_enqueue;
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = remote_socket_ready;
511818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    s->shutdown = remote_socket_shutdown;
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = remote_socket_close;
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->transport = t;
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5157a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("RS(%d): created", s->id);
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51963760409ad833cf803482e098367f49741b5f6d3Josh Gaovoid connect_to_remote(asocket* s, const char* destination) {
5207a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("Connect_to_remote call RS(%d) fd=%d", s->id, s->fd);
52163760409ad833cf803482e098367f49741b5f6d3Josh Gao    apacket* p = get_apacket();
5223d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    size_t len = strlen(destination) + 1;
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
52463760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (len > (s->get_max_payload() - 1)) {
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fatal("destination oversized");
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5287a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("LS(%d): connect('%s')", s->id, destination);
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_OPEN;
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = s->id;
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.data_length = len;
53263760409ad833cf803482e098367f49741b5f6d3Josh Gao    strcpy((char*)p->data, destination);
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* this is used by magic sockets to rig local sockets to
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   send the go-ahead message when they connect */
53863760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void local_socket_ready_notify(asocket* s) {
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = local_socket_ready;
540818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    s->shutdown = NULL;
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = local_socket_close;
542e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    SendOkay(s->fd);
543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready(s);
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* this is used by magic sockets to rig local sockets to
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   send the failure message if they are closed before
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   connected (to avoid closing them without a status message) */
54963760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void local_socket_close_notify(asocket* s) {
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = local_socket_ready;
551818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    s->shutdown = NULL;
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = local_socket_close;
553e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    SendFail(s->fd, "closed");
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close(s);
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55763760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic unsigned unhex(unsigned char* s, int len) {
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned n = 0, c;
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
56063760409ad833cf803482e098367f49741b5f6d3Josh Gao    while (len-- > 0) {
56163760409ad833cf803482e098367f49741b5f6d3Josh Gao        switch ((c = *s++)) {
56263760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '0':
56363760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '1':
56463760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '2':
56563760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '3':
56663760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '4':
56763760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '5':
56863760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '6':
56963760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '7':
57063760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '8':
57163760409ad833cf803482e098367f49741b5f6d3Josh Gao            case '9':
57263760409ad833cf803482e098367f49741b5f6d3Josh Gao                c -= '0';
57363760409ad833cf803482e098367f49741b5f6d3Josh Gao                break;
57463760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'a':
57563760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'b':
57663760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'c':
57763760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'd':
57863760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'e':
57963760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'f':
58063760409ad833cf803482e098367f49741b5f6d3Josh Gao                c = c - 'a' + 10;
58163760409ad833cf803482e098367f49741b5f6d3Josh Gao                break;
58263760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'A':
58363760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'B':
58463760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'C':
58563760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'D':
58663760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'E':
58763760409ad833cf803482e098367f49741b5f6d3Josh Gao            case 'F':
58863760409ad833cf803482e098367f49741b5f6d3Josh Gao                c = c - 'A' + 10;
58963760409ad833cf803482e098367f49741b5f6d3Josh Gao                break;
59063760409ad833cf803482e098367f49741b5f6d3Josh Gao            default:
59163760409ad833cf803482e098367f49741b5f6d3Josh Gao                return 0xffffffff;
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        n = (n << 4) | c;
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return n;
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
600e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes#if ADB_HOST
601e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes
602802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursellnamespace internal {
603802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell
604802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell// Returns the position in |service| following the target serial parameter. Serial format can be
605802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell// any of:
606802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell//   * [tcp:|udp:]<serial>[:<port>]:<command>
607802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell//   * <prefix>:<serial>:<command>
608802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell// Where <port> must be a base-10 number and <prefix> may be any of {usb,product,model,device}.
609802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell//
610802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell// The returned pointer will point to the ':' just before <command>, or nullptr if not found.
611802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursellchar* skip_host_serial(const char* service) {
612802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell    static const std::vector<std::string>& prefixes =
613802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell        *(new std::vector<std::string>{"usb:", "product:", "model:", "device:"});
614802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell
615802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell    for (const std::string& prefix : prefixes) {
616802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell        if (!strncmp(service, prefix.c_str(), prefix.length())) {
617802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell            return strchr(service + prefix.length(), ':');
618802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell        }
619802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell    }
620802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell
621802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell    // For fastboot compatibility, ignore protocol prefixes.
622802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell    if (!strncmp(service, "tcp:", 4) || !strncmp(service, "udp:", 4)) {
623802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell        service += 4;
6243608d832425ca3a6d00c4040f3bb979c5aa49899Scott Anderson    }
6253608d832425ca3a6d00c4040f3bb979c5aa49899Scott Anderson
626802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell    char* first_colon = strchr(service, ':');
62728e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    if (!first_colon) {
628802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell        // No colon in service string.
629802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell        return nullptr;
63028e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    }
631802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell
632802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell    char* serial_end = first_colon;
63328e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    if (isdigit(serial_end[1])) {
63428e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        serial_end++;
635802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell        while (*serial_end && isdigit(*serial_end)) {
63628e1390e688f721e13a9877d3c41884bf151db60Terence Haddock            serial_end++;
63728e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        }
638802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell        if (*serial_end != ':') {
63928e1390e688f721e13a9877d3c41884bf151db60Terence Haddock            // Something other than numbers was found, reset the end.
64028e1390e688f721e13a9877d3c41884bf151db60Terence Haddock            serial_end = first_colon;
64128e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        }
64228e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    }
64328e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    return serial_end;
64428e1390e688f721e13a9877d3c41884bf151db60Terence Haddock}
64528e1390e688f721e13a9877d3c41884bf151db60Terence Haddock
646802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell}  // namespace internal
647802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell
64863760409ad833cf803482e098367f49741b5f6d3Josh Gao#endif  // ADB_HOST
649e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes
65063760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic int smart_socket_enqueue(asocket* s, apacket* p) {
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned len;
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
65363760409ad833cf803482e098367f49741b5f6d3Josh Gao    char* service = nullptr;
6548d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    char* serial = nullptr;
6553bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes    TransportType type = kTransportAny;
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6587a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("SS(%d): enqueue %d", s->id, p->len);
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
66063760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s->pkt_first == 0) {
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_first = p;
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_last = p;
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
66463760409ad833cf803482e098367f49741b5f6d3Josh Gao        if ((s->pkt_first->len + p->len) > s->get_max_payload()) {
6657a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui            D("SS(%d): overflow", s->id);
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            put_apacket(p);
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
67063760409ad833cf803482e098367f49741b5f6d3Josh Gao        memcpy(s->pkt_first->data + s->pkt_first->len, p->data, p->len);
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_first->len += p->len;
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(p);
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p = s->pkt_first;
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6777e6683ce40ba79c94ccc1e3b984cd39e63651dd5Josh Gao    /* don't bother if we can't decode the length */
67863760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (p->len < 4) {
67963760409ad833cf803482e098367f49741b5f6d3Josh Gao        return 0;
68063760409ad833cf803482e098367f49741b5f6d3Josh Gao    }
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = unhex(p->data, 4);
6837e6683ce40ba79c94ccc1e3b984cd39e63651dd5Josh Gao    if ((len < 1) || (len > MAX_PAYLOAD_V1)) {
6847a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("SS(%d): bad size (%d)", s->id, len);
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
68863760409ad833cf803482e098367f49741b5f6d3Josh Gao    D("SS(%d): len is %d", s->id, len);
6897e6683ce40ba79c94ccc1e3b984cd39e63651dd5Josh Gao    /* can't do anything until we have the full header */
69063760409ad833cf803482e098367f49741b5f6d3Josh Gao    if ((len + 4) > p->len) {
69163760409ad833cf803482e098367f49741b5f6d3Josh Gao        D("SS(%d): waiting for %d more bytes", s->id, len + 4 - p->len);
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->data[len + 4] = 0;
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
69763760409ad833cf803482e098367f49741b5f6d3Josh Gao    D("SS(%d): '%s'", s->id, (char*)(p->data + 4));
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
70063760409ad833cf803482e098367f49741b5f6d3Josh Gao    service = (char*)p->data + 4;
70163760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (!strncmp(service, "host-serial:", strlen("host-serial:"))) {
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char* serial_end;
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host-serial:");
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
70528e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        // serial number should follow "host:" and could be a host:port string.
706802c54ebb79453256a8c7fd3c3cab88acc8a84e8David Pursell        serial_end = internal::skip_host_serial(service);
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (serial_end) {
70863760409ad833cf803482e098367f49741b5f6d3Josh Gao            *serial_end = 0;  // terminate string
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            serial = service;
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            service = serial_end + 1;
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
7133bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes        type = kTransportUsb;
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host-usb:");
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(service, "host-local:", strlen("host-local:"))) {
7163bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes        type = kTransportLocal;
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host-local:");
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(service, "host:", strlen("host:"))) {
7193bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes        type = kTransportAny;
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host:");
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
7228d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        service = nullptr;
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (service) {
72663760409ad833cf803482e098367f49741b5f6d3Josh Gao        asocket* s2;
72763760409ad833cf803482e098367f49741b5f6d3Josh Gao
72863760409ad833cf803482e098367f49741b5f6d3Josh Gao        /* some requests are handled immediately -- in that
72963760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** case the handle_host_request() routine has sent
73063760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** the OKAY or FAIL message and all we have to do
73163760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** is clean up.
73263760409ad833cf803482e098367f49741b5f6d3Josh Gao        */
73363760409ad833cf803482e098367f49741b5f6d3Josh Gao        if (handle_host_request(service, type, serial, s->peer->fd, s) == 0) {
73463760409ad833cf803482e098367f49741b5f6d3Josh Gao            /* XXX fail message? */
73563760409ad833cf803482e098367f49741b5f6d3Josh Gao            D("SS(%d): handled host service '%s'", s->id, service);
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strncmp(service, "transport", strlen("transport"))) {
73963760409ad833cf803482e098367f49741b5f6d3Josh Gao            D("SS(%d): okay transport", s->id);
740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p->len = 0;
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74463760409ad833cf803482e098367f49741b5f6d3Josh Gao        /* try to find a local service with this name.
74563760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** if no such service exists, we'll fail out
74663760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** and tear down here.
74763760409ad833cf803482e098367f49741b5f6d3Josh Gao        */
748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s2 = create_host_service_socket(service, serial);
74963760409ad833cf803482e098367f49741b5f6d3Josh Gao        if (s2 == 0) {
75063760409ad833cf803482e098367f49741b5f6d3Josh Gao            D("SS(%d): couldn't create host service '%s'", s->id, service);
751e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            SendFail(s->peer->fd, "unknown host service");
752dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
753dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
754dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75563760409ad833cf803482e098367f49741b5f6d3Josh Gao        /* we've connected to a local host service,
75663760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** so we make our peer back into a regular
75763760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** local socket and bind it to the new local
75863760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** service socket, acknowledge the successful
75963760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** connection, and close this smart socket now
76063760409ad833cf803482e098367f49741b5f6d3Josh Gao        ** that its work is done.
76163760409ad833cf803482e098367f49741b5f6d3Josh Gao        */
762e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        SendOkay(s->peer->fd);
763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->ready = local_socket_ready;
7658d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        s->peer->shutdown = nullptr;
766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->close = local_socket_close;
767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = s2;
768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s2->peer = s->peer;
769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer = 0;
77063760409ad833cf803482e098367f49741b5f6d3Josh Gao        D("SS(%d): okay", s->id);
771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->close(s);
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
77363760409ad833cf803482e098367f49741b5f6d3Josh Gao        /* initial state is "ready" */
774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s2->ready(s2);
775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /* !ADB_HOST */
7788d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    if (s->transport == nullptr) {
7797be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes        std::string error_msg = "unknown failure";
7808d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        s->transport = acquire_one_transport(kTransportAny, nullptr, nullptr, &error_msg);
7818d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        if (s->transport == nullptr) {
782e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            SendFail(s->peer->fd, error_msg);
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78863760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (!(s->transport) || (s->transport->connection_state == kCsOffline)) {
78963760409ad833cf803482e098367f49741b5f6d3Josh Gao        /* if there's no remote we fail the connection
79063760409ad833cf803482e098367f49741b5f6d3Josh Gao         ** right here and terminate it
79163760409ad833cf803482e098367f49741b5f6d3Josh Gao         */
792e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        SendFail(s->peer->fd, "device offline (x)");
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
79663760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* instrument our peer to pass the success or fail
79763760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** message back once it connects or closes, then
79863760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** detach from it, request the connection, and
79963760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** tear down
80063760409ad833cf803482e098367f49741b5f6d3Josh Gao    */
801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->ready = local_socket_ready_notify;
8028d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    s->peer->shutdown = nullptr;
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->close = local_socket_close_notify;
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->peer = 0;
80563760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* give him our transport and upref it */
806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->transport = s->transport;
807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
80863760409ad833cf803482e098367f49741b5f6d3Josh Gao    connect_to_remote(s->peer, (char*)(p->data + 4));
809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer = 0;
810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close(s);
811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
81463760409ad833cf803482e098367f49741b5f6d3Josh Gao    /* we're going to close our peer as a side-effect, so
81563760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** return -1 to signal that state to the local socket
81663760409ad833cf803482e098367f49741b5f6d3Josh Gao    ** who is enqueueing against us
81763760409ad833cf803482e098367f49741b5f6d3Josh Gao    */
818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close(s);
819dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
821dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82263760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void smart_socket_ready(asocket* s) {
8237a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("SS(%d): ready", s->id);
824dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
825dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82663760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic void smart_socket_close(asocket* s) {
8277a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("SS(%d): closed", s->id);
82863760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s->pkt_first) {
829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(s->pkt_first);
830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
83163760409ad833cf803482e098367f49741b5f6d3Josh Gao    if (s->peer) {
832dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = 0;
833dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->close(s->peer);
83449f1857dd8b64cdd57f28e965a1ff5fa0c2b0547Tom Marlin        s->peer = 0;
835dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
836dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
837dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
838dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83963760409ad833cf803482e098367f49741b5f6d3Josh Gaostatic asocket* create_smart_socket(void) {
8407a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("Creating smart socket");
84163760409ad833cf803482e098367f49741b5f6d3Josh Gao    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
842c419e2a210ad7e37a1f749f2ab4de7c7f95b90d7André Goddard Rosa    if (s == NULL) fatal("cannot allocate socket");
843dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->enqueue = smart_socket_enqueue;
844dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = smart_socket_ready;
845818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    s->shutdown = NULL;
846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = smart_socket_close;
847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8487a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("SS(%d)", s->id);
849dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
851dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
85263760409ad833cf803482e098367f49741b5f6d3Josh Gaovoid connect_to_smartsocket(asocket* s) {
8537a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("Connecting to smart socket");
85463760409ad833cf803482e098367f49741b5f6d3Josh Gao    asocket* ss = create_smart_socket();
855dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer = ss;
856dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ss->peer = s;
857dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready(s);
858dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
8593d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer
8603d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammersize_t asocket::get_max_payload() const {
8613d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    size_t max_payload = MAX_PAYLOAD;
8623d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    if (transport) {
8633d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        max_payload = std::min(max_payload, transport->get_max_payload());
8643d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    }
8653d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    if (peer && peer->transport) {
8663d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        max_payload = std::min(max_payload, peer->transport->get_max_payload());
8673d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    }
8683d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    return max_payload;
8693d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer}
870