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>
299b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh Gao#include <mutex>
303f902aad5b427a8162bf860a758878b55b13e775David Pursell#include <string>
313f902aad5b427a8162bf860a758878b55b13e775David Pursell#include <vector>
32363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low
337664901a355b959f312e9acff5a0fd31b7139623Dan Albert#if !ADB_HOST
34ffdec180176094dac0fb902263370dea1deb138fElliott Hughes#include <android-base/properties.h>
351f83aa424f537cf3f07e1d27dbbcc524818b5358Steven Moreland#include <log/log_properties.h>
367664901a355b959f312e9acff5a0fd31b7139623Dan Albert#endif
373313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
383313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "adb.h"
393313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "adb_io.h"
407664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include "transport.h"
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
429b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh 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 = {
4652bd8526aaaf10511177fb42c55c26bc722b0833Josh 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 = {
5452bd8526aaaf10511177fb42c55c26bc722b0833Josh 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.
6052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaoasocket* find_local_socket(unsigned local_id, unsigned peer_id) {
6152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    asocket* s;
6252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    asocket* result = NULL;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
649b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh 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) {
6652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        if (s->id != local_id) {
67818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner            continue;
6852bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
7852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic void insert_local_socket(asocket* s, asocket* list) {
7952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    s->next = list;
8052bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
8552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaovoid install_local_socket(asocket* s) {
869b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh 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.
9152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (local_socket_next_id == 0) {
929b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh Gao        fatal("local socket id overflow");
9352bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
9852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaovoid remove_socket(asocket* s) {
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // socket_list_lock should already be held
10052bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
10952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaovoid close_all_sockets(atransport* t) {
11052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    asocket* s;
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
11252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* this is a little gross, but since s->close() *will* modify
11352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** the list out from under you, your options are limited.
11452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    */
1159b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh Gao    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectrestart:
11752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
11852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        if (s->transport == t || (s->peer && s->peer->transport == t)) {
11953eb31d87cb84a4212f4850bf745646e1fb12814Josh 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
12552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic int local_socket_enqueue(asocket* s, apacket* p) {
12606d61d4d96d28777f76578fb5d3c823168853166Josh Gao    D("LS(%d): enqueue %zu", s->id, p->len);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->ptr = p->data;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
13052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* if there is already data queue'd, we will receive
13152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** events when it's time to write.  just add this to
13252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** the tail
13352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    */
13452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (s->pkt_first) {
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto enqueue;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
13852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* write as much as we can, until we
13952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** would block or there is an error/eof
14052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    */
14152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    while (p->len > 0) {
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int r = adb_write(s->fd, p->ptr, p->len);
14352bd8526aaaf10511177fb42c55c26bc722b0833Josh 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        }
14852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        if ((r == 0) || (errno != EAGAIN)) {
14952bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
15952bd8526aaaf10511177fb42c55c26bc722b0833Josh 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;
16652bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
17352bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
17952bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
18652bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
19252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* IMPORTANT: the remove closes the fd
19352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** that belongs to this socket
19452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    */
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_remove(&s->fde);
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* dispose of any unwritten data */
19852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    for (p = s->pkt_first; p; p = n) {
19906d61d4d96d28777f76578fb5d3c823168853166Josh Gao        D("LS(%d): discarding %zu 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
2129b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh Gaostatic void local_socket_close(asocket* s) {
2139b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh Gao    D("entered local_socket_close. LS(%d) fd=%d", s->id, s->fd);
2149b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh Gao    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
21552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (s->peer) {
21652bd8526aaaf10511177fb42c55c26bc722b0833Josh 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. */
22152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        if (s->peer->shutdown) {
22252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            s->peer->shutdown(s->peer);
22352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        }
2249b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh Gao        s->peer->peer = nullptr;
2259b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh Gao        s->peer->close(s->peer);
2269b587dec6d0a57c8fe1083c1c543fbeb163d65faJosh Gao        s->peer = nullptr;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
22952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* If we are already closing, or if there are no
23052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** pending packets, destroy immediately
23152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    */
232c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin Cui    if (s->closing || s->has_write_error || s->pkt_first == NULL) {
23352bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
23952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* otherwise, put on the closing list
24052bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
25052bd8526aaaf10511177fb42c55c26bc722b0833Josh 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) {
30852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        apacket* p = get_apacket();
30906d61d4d96d28777f76578fb5d3c823168853166Josh Gao        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);
31752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu", s->id, s->fd, r,
31852bd8526aaaf10511177fb42c55c26bc722b0833Josh 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        }
33352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d", s->id, s->fd, r, is_eof,
33452bd8526aaaf10511177fb42c55c26bc722b0833Josh 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) {
34852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                /* error return means they closed us as a side-effect
34952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                ** and we must return immediately.
35052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                **
35152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                ** note that if we still have buffered packets, the
35252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                ** socket will be placed on the closing socket list.
35352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                ** this handler function will be called again
35452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                ** to process FDE_WRITE events.
35552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                */
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
359bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert            if (r > 0) {
36052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                /* if the remote cannot accept further events,
36152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                ** we disable notification of READs.  They'll
36252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                ** be enabled again when we get a call to ready()
36352bd8526aaaf10511177fb42c55c26bc722b0833Josh 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) {
36952bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
37552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (ev & FDE_ERROR) {
37652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        /* this should be caught be the next read or write
37752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** catching it here means we may skip the last few
37852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** bytes of readable data.
37952bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
38552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaoasocket* create_local_socket(int fd) {
38652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
38752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (s == NULL) {
38852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        fatal("cannot allocate socket");
38952bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
40252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaoasocket* create_local_service_socket(const char* name, const atransport* transport) {
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if !ADB_HOST
40452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (!strcmp(name, "jdwp")) {
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return create_jdwp_service_socket();
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
40752bd8526aaaf10511177fb42c55c26bc722b0833Josh 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);
41252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (fd < 0) {
413ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes        return nullptr;
41452bd8526aaaf10511177fb42c55c26bc722b0833Josh 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
42097787a00e6aeb9aba2d744566cfd9de3d2f8c4f6Mark Salyzyn    if ((!strncmp(name, "root:", 5) && getuid() != 0 && __android_log_is_debuggable()) ||
42152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        (!strncmp(name, "unroot:", 7) && getuid() == 0) ||
42252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        !strncmp(name, "usb:", 4) ||
42352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        !strncmp(name, "tcpip:", 6)) {
4247a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("LS(%d): enabling exit_on_close", s->id);
425f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby        s->exit_on_close = 1;
426f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby    }
427f91259a8f0d75d721761d588a4b811427565c984JP Abgrall#endif
428f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
43352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic asocket* create_host_service_socket(const char* name, const char* serial) {
43452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    asocket* s;
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s = host_service_to_socket(name, serial);
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s != NULL) {
4397a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("LS(%d) bound to '%s'", s->id, name);
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return s;
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* ADB_HOST */
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic int remote_socket_enqueue(asocket* s, apacket* p) {
44852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_WRTE;
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = s->peer->id;
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = s->id;
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.data_length = p->len;
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic void remote_socket_ready(asocket* s) {
45852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
45952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    apacket* p = get_apacket();
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_OKAY;
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = s->peer->id;
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = s->id;
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic void remote_socket_shutdown(asocket* s) {
46752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d", s->id, s->fd,
46852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao      s->peer ? s->peer->fd : -1);
46952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    apacket* p = get_apacket();
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_CLSE;
47152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (s->peer) {
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p->msg.arg0 = s->peer->id;
473818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    }
474818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    p->msg.arg1 = s->id;
475818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    send_packet(p, s->transport);
476818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner}
477818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner
47852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic void remote_socket_close(asocket* s) {
479818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    if (s->peer) {
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = 0;
48152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->close(s->peer);
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
48452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d", s->id, s->fd,
48552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao      s->peer ? s->peer->fd : -1);
4867a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("RS(%d): closed", s->id);
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
490fd28f327ee0e110208ef42ded829286643860394Yabin Cui// Create a remote socket to exchange packets with a remote service through transport
491fd28f327ee0e110208ef42ded829286643860394Yabin Cui// |t|. Where |id| is the socket id of the corresponding service on the other
492fd28f327ee0e110208ef42ded829286643860394Yabin Cui//  side of the transport (it is allocated by the remote side and _cannot_ be 0).
493fd28f327ee0e110208ef42ded829286643860394Yabin Cui// Returns a new non-NULL asocket handle.
49452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaoasocket* create_remote_socket(unsigned id, atransport* t) {
49552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (id == 0) {
49652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        fatal("invalid remote socket id (0)");
49752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    }
498fd28f327ee0e110208ef42ded829286643860394Yabin Cui    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (s == NULL) {
50152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        fatal("cannot allocate socket");
50252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    }
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->id = id;
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->enqueue = remote_socket_enqueue;
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = remote_socket_ready;
506818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    s->shutdown = remote_socket_shutdown;
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = remote_socket_close;
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->transport = t;
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5107a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("RS(%d): created", s->id);
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaovoid connect_to_remote(asocket* s, const char* destination) {
5157a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("Connect_to_remote call RS(%d) fd=%d", s->id, s->fd);
51652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    apacket* p = get_apacket();
5173d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    size_t len = strlen(destination) + 1;
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (len > (s->get_max_payload() - 1)) {
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fatal("destination oversized");
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5237a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("LS(%d): connect('%s')", s->id, destination);
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_OPEN;
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = s->id;
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.data_length = len;
52752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    strcpy((char*)p->data, destination);
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* this is used by magic sockets to rig local sockets to
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   send the go-ahead message when they connect */
53352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic void local_socket_ready_notify(asocket* s) {
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = local_socket_ready;
535818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    s->shutdown = NULL;
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = local_socket_close;
537e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    SendOkay(s->fd);
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready(s);
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* this is used by magic sockets to rig local sockets to
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   send the failure message if they are closed before
543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   connected (to avoid closing them without a status message) */
54452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic void local_socket_close_notify(asocket* s) {
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = local_socket_ready;
546818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    s->shutdown = NULL;
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = local_socket_close;
548e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    SendFail(s->fd, "closed");
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close(s);
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55206d61d4d96d28777f76578fb5d3c823168853166Josh Gaostatic unsigned unhex(char* s, int len) {
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned n = 0, c;
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    while (len-- > 0) {
55652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        switch ((c = *s++)) {
55752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '0':
55852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '1':
55952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '2':
56052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '3':
56152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '4':
56252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '5':
56352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '6':
56452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '7':
56552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '8':
56652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case '9':
56752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                c -= '0';
56852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                break;
56952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'a':
57052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'b':
57152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'c':
57252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'd':
57352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'e':
57452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'f':
57552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                c = c - 'a' + 10;
57652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                break;
57752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'A':
57852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'B':
57952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'C':
58052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'D':
58152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'E':
58252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            case 'F':
58352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                c = c - 'A' + 10;
58452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                break;
58552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            default:
58652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao                return 0xffffffff;
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        n = (n << 4) | c;
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return n;
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
595e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes#if ADB_HOST
596e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes
5973f902aad5b427a8162bf860a758878b55b13e775David Pursellnamespace internal {
5983f902aad5b427a8162bf860a758878b55b13e775David Pursell
5993f902aad5b427a8162bf860a758878b55b13e775David Pursell// Returns the position in |service| following the target serial parameter. Serial format can be
6003f902aad5b427a8162bf860a758878b55b13e775David Pursell// any of:
6013f902aad5b427a8162bf860a758878b55b13e775David Pursell//   * [tcp:|udp:]<serial>[:<port>]:<command>
6023f902aad5b427a8162bf860a758878b55b13e775David Pursell//   * <prefix>:<serial>:<command>
6033f902aad5b427a8162bf860a758878b55b13e775David Pursell// Where <port> must be a base-10 number and <prefix> may be any of {usb,product,model,device}.
6043f902aad5b427a8162bf860a758878b55b13e775David Pursell//
6053f902aad5b427a8162bf860a758878b55b13e775David Pursell// The returned pointer will point to the ':' just before <command>, or nullptr if not found.
606b4cff495a1f93b6c92f4327cbfb9e564b28913d8Dan Austinchar* skip_host_serial(char* service) {
6073f902aad5b427a8162bf860a758878b55b13e775David Pursell    static const std::vector<std::string>& prefixes =
6083f902aad5b427a8162bf860a758878b55b13e775David Pursell        *(new std::vector<std::string>{"usb:", "product:", "model:", "device:"});
6093f902aad5b427a8162bf860a758878b55b13e775David Pursell
6103f902aad5b427a8162bf860a758878b55b13e775David Pursell    for (const std::string& prefix : prefixes) {
6113f902aad5b427a8162bf860a758878b55b13e775David Pursell        if (!strncmp(service, prefix.c_str(), prefix.length())) {
6123f902aad5b427a8162bf860a758878b55b13e775David Pursell            return strchr(service + prefix.length(), ':');
6133f902aad5b427a8162bf860a758878b55b13e775David Pursell        }
6143f902aad5b427a8162bf860a758878b55b13e775David Pursell    }
6153f902aad5b427a8162bf860a758878b55b13e775David Pursell
6163f902aad5b427a8162bf860a758878b55b13e775David Pursell    // For fastboot compatibility, ignore protocol prefixes.
6173f902aad5b427a8162bf860a758878b55b13e775David Pursell    if (!strncmp(service, "tcp:", 4) || !strncmp(service, "udp:", 4)) {
6183f902aad5b427a8162bf860a758878b55b13e775David Pursell        service += 4;
6193608d832425ca3a6d00c4040f3bb979c5aa49899Scott Anderson    }
6203608d832425ca3a6d00c4040f3bb979c5aa49899Scott Anderson
62173d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell    // Check for an IPv6 address. `adb connect` creates the serial number from the canonical
62273d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell    // network address so it will always have the [] delimiters.
62373d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell    if (service[0] == '[') {
62473d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell        char* ipv6_end = strchr(service, ']');
62573d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell        if (ipv6_end != nullptr) {
62673d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell            service = ipv6_end;
62773d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell        }
62873d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell    }
62973d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell
63073d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell    // The next colon we find must either begin the port field or the command field.
63173d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell    char* colon_ptr = strchr(service, ':');
63273d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell    if (!colon_ptr) {
6333f902aad5b427a8162bf860a758878b55b13e775David Pursell        // No colon in service string.
6343f902aad5b427a8162bf860a758878b55b13e775David Pursell        return nullptr;
63528e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    }
6363f902aad5b427a8162bf860a758878b55b13e775David Pursell
63773d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell    // If the next field is only decimal digits and ends with another colon, it's a port.
63873d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell    char* serial_end = colon_ptr;
63928e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    if (isdigit(serial_end[1])) {
64028e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        serial_end++;
6413f902aad5b427a8162bf860a758878b55b13e775David Pursell        while (*serial_end && isdigit(*serial_end)) {
64228e1390e688f721e13a9877d3c41884bf151db60Terence Haddock            serial_end++;
64328e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        }
6443f902aad5b427a8162bf860a758878b55b13e775David Pursell        if (*serial_end != ':') {
64573d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell            // Something other than "<port>:" was found, this must be the command field instead.
64673d55aaab23256f85941730444e82cbc41a63f8bDavid Pursell            serial_end = colon_ptr;
64728e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        }
64828e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    }
64928e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    return serial_end;
65028e1390e688f721e13a9877d3c41884bf151db60Terence Haddock}
65128e1390e688f721e13a9877d3c41884bf151db60Terence Haddock
6523f902aad5b427a8162bf860a758878b55b13e775David Pursell}  // namespace internal
6533f902aad5b427a8162bf860a758878b55b13e775David Pursell
65452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao#endif  // ADB_HOST
655e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes
65652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic int smart_socket_enqueue(asocket* s, apacket* p) {
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned len;
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
65952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    char* service = nullptr;
6608d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    char* serial = nullptr;
6613bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes    TransportType type = kTransportAny;
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
66406d61d4d96d28777f76578fb5d3c823168853166Josh Gao    D("SS(%d): enqueue %zu", s->id, p->len);
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
66652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (s->pkt_first == 0) {
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_first = p;
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_last = p;
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
67052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        if ((s->pkt_first->len + p->len) > s->get_max_payload()) {
6717a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui            D("SS(%d): overflow", s->id);
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            put_apacket(p);
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
67652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        memcpy(s->pkt_first->data + s->pkt_first->len, p->data, p->len);
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_first->len += p->len;
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(p);
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p = s->pkt_first;
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6837e6683ce40ba79c94ccc1e3b984cd39e63651dd5Josh Gao    /* don't bother if we can't decode the length */
68452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (p->len < 4) {
68552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        return 0;
68652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    }
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = unhex(p->data, 4);
6897e6683ce40ba79c94ccc1e3b984cd39e63651dd5Josh Gao    if ((len < 1) || (len > MAX_PAYLOAD_V1)) {
6907a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("SS(%d): bad size (%d)", s->id, len);
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
69452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    D("SS(%d): len is %d", s->id, len);
6957e6683ce40ba79c94ccc1e3b984cd39e63651dd5Josh Gao    /* can't do anything until we have the full header */
69652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if ((len + 4) > p->len) {
69706d61d4d96d28777f76578fb5d3c823168853166Josh Gao        D("SS(%d): waiting for %zu more bytes", s->id, len + 4 - p->len);
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->data[len + 4] = 0;
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
70352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    D("SS(%d): '%s'", s->id, (char*)(p->data + 4));
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
70652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    service = (char*)p->data + 4;
70752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (!strncmp(service, "host-serial:", strlen("host-serial:"))) {
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char* serial_end;
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host-serial:");
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
71128e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        // serial number should follow "host:" and could be a host:port string.
7123f902aad5b427a8162bf860a758878b55b13e775David Pursell        serial_end = internal::skip_host_serial(service);
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (serial_end) {
71452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            *serial_end = 0;  // terminate string
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            serial = service;
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            service = serial_end + 1;
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
7193bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes        type = kTransportUsb;
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host-usb:");
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(service, "host-local:", strlen("host-local:"))) {
7223bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes        type = kTransportLocal;
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host-local:");
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(service, "host:", strlen("host:"))) {
7253bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes        type = kTransportAny;
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host:");
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
7288d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        service = nullptr;
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (service) {
73252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        asocket* s2;
73352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao
73452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        /* some requests are handled immediately -- in that
73552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** case the handle_host_request() routine has sent
73652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** the OKAY or FAIL message and all we have to do
73752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** is clean up.
73852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        */
73952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        if (handle_host_request(service, type, serial, s->peer->fd, s) == 0) {
74052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            /* XXX fail message? */
74152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            D("SS(%d): handled host service '%s'", s->id, service);
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strncmp(service, "transport", strlen("transport"))) {
74552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            D("SS(%d): okay transport", s->id);
746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p->len = 0;
747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
749dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        /* try to find a local service with this name.
75152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** if no such service exists, we'll fail out
75252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** and tear down here.
75352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        */
754dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s2 = create_host_service_socket(service, serial);
75552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        if (s2 == 0) {
75652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao            D("SS(%d): couldn't create host service '%s'", s->id, service);
757e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            SendFail(s->peer->fd, "unknown host service");
758dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
759dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
76152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        /* we've connected to a local host service,
76252bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** so we make our peer back into a regular
76352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** local socket and bind it to the new local
76452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** service socket, acknowledge the successful
76552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** connection, and close this smart socket now
76652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        ** that its work is done.
76752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        */
768e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        SendOkay(s->peer->fd);
769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->ready = local_socket_ready;
7718d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        s->peer->shutdown = nullptr;
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->close = local_socket_close;
773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = s2;
774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s2->peer = s->peer;
775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer = 0;
77652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        D("SS(%d): okay", s->id);
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->close(s);
778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
77952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        /* initial state is "ready" */
780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s2->ready(s2);
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /* !ADB_HOST */
7848d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    if (s->transport == nullptr) {
7857be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes        std::string error_msg = "unknown failure";
7868d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        s->transport = acquire_one_transport(kTransportAny, nullptr, nullptr, &error_msg);
7878d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        if (s->transport == nullptr) {
788e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            SendFail(s->peer->fd, error_msg);
789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
79422d2b3e1c2e1152ca9cf86c3eb42cd42e7448a31Josh Gao    if (!s->transport) {
79522d2b3e1c2e1152ca9cf86c3eb42cd42e7448a31Josh Gao        SendFail(s->peer->fd, "device offline (no transport)");
79622d2b3e1c2e1152ca9cf86c3eb42cd42e7448a31Josh Gao        goto fail;
79722d2b3e1c2e1152ca9cf86c3eb42cd42e7448a31Josh Gao    } else if (s->transport->connection_state == kCsOffline) {
79852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao        /* if there's no remote we fail the connection
79952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao         ** right here and terminate it
80052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao         */
80122d2b3e1c2e1152ca9cf86c3eb42cd42e7448a31Josh Gao        SendFail(s->peer->fd, "device offline (transport offline)");
802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
80552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* instrument our peer to pass the success or fail
80652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** message back once it connects or closes, then
80752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** detach from it, request the connection, and
80852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** tear down
80952bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    */
810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->ready = local_socket_ready_notify;
8118d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    s->peer->shutdown = nullptr;
812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->close = local_socket_close_notify;
813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->peer = 0;
81452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* give him our transport and upref it */
815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->transport = s->transport;
816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
81752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    connect_to_remote(s->peer, (char*)(p->data + 4));
818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer = 0;
819dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close(s);
820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
821dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
822dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
82352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    /* we're going to close our peer as a side-effect, so
82452bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** return -1 to signal that state to the local socket
82552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    ** who is enqueueing against us
82652bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    */
827dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close(s);
828dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic void smart_socket_ready(asocket* s) {
8327a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("SS(%d): ready", s->id);
833dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
834dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83552bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic void smart_socket_close(asocket* s) {
8367a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("SS(%d): closed", s->id);
83752bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (s->pkt_first) {
838dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(s->pkt_first);
839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
84052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    if (s->peer) {
841dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = 0;
842dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->close(s->peer);
84349f1857dd8b64cdd57f28e965a1ff5fa0c2b0547Tom Marlin        s->peer = 0;
844dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
84852bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaostatic asocket* create_smart_socket(void) {
8497a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("Creating smart socket");
85052bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
851c419e2a210ad7e37a1f749f2ab4de7c7f95b90d7André Goddard Rosa    if (s == NULL) fatal("cannot allocate socket");
852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->enqueue = smart_socket_enqueue;
853dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = smart_socket_ready;
854818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    s->shutdown = NULL;
855dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = smart_socket_close;
856dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8577a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("SS(%d)", s->id);
858dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
859dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
860dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86152bd8526aaaf10511177fb42c55c26bc722b0833Josh Gaovoid connect_to_smartsocket(asocket* s) {
8627a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("Connecting to smart socket");
86352bd8526aaaf10511177fb42c55c26bc722b0833Josh Gao    asocket* ss = create_smart_socket();
864dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer = ss;
865dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ss->peer = s;
866dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready(s);
867dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
8683d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer
8693d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammersize_t asocket::get_max_payload() const {
8703d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    size_t max_payload = MAX_PAYLOAD;
8713d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    if (transport) {
8723d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        max_payload = std::min(max_payload, transport->get_max_payload());
8733d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    }
8743d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    if (peer && peer->transport) {
8753d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        max_payload = std::min(max_payload, peer->transport->get_max_payload());
8763d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    }
8773d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    return max_payload;
8783d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer}
879