sockets.c revision f91259a8f0d75d721761d588a4b811427565c984
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
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h"
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  TRACE_TAG  TRACE_SOCKETS
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h"
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectADB_MUTEX_DEFINE( socket_list_lock );
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void local_socket_close_locked(asocket *s);
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint sendfailmsg(int fd, const char *reason)
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char buf[9];
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len;
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = strlen(reason);
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(len > 0xffff) len = 0xffff;
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    snprintf(buf, sizeof buf, "FAIL%04x", len);
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(writex(fd, buf, 8)) return -1;
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return writex(fd, reason, len);
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//extern int online;
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic unsigned local_socket_next_id = 1;
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic asocket local_socket_list = {
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .next = &local_socket_list,
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .prev = &local_socket_list,
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* the the list of currently closing local sockets.
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** these have no peer anymore, but still packets to
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** write to their fd.
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic asocket local_socket_closing_list = {
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .next = &local_socket_closing_list,
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .prev = &local_socket_closing_list,
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket *find_local_socket(unsigned id)
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s;
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *result = NULL;
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&socket_list_lock);
688182829ccb46fc5b043ea258672602dc2928dee2André Goddard Rosa    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
698182829ccb46fc5b043ea258672602dc2928dee2André Goddard Rosa        if (s->id == id) {
708182829ccb46fc5b043ea258672602dc2928dee2André Goddard Rosa            result = s;
718182829ccb46fc5b043ea258672602dc2928dee2André Goddard Rosa            break;
728182829ccb46fc5b043ea258672602dc2928dee2André Goddard Rosa        }
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&socket_list_lock);
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinsert_local_socket(asocket*  s, asocket*  list)
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->next       = list;
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->prev       = s->next->prev;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->prev->next = s;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->next->prev = s;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid install_local_socket(asocket *s)
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&socket_list_lock);
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->id = local_socket_next_id++;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    insert_local_socket(s, &local_socket_list);
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&socket_list_lock);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid remove_socket(asocket *s)
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // socket_list_lock should already be held
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s->prev && s->next)
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->prev->next = s->next;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->next->prev = s->prev;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->next = 0;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->prev = 0;
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->id = 0;
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid close_all_sockets(atransport *t)
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* this is a little gross, but since s->close() *will* modify
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** the list out from under you, your options are limited.
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&socket_list_lock);
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectrestart:
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(s = local_socket_list.next; s != &local_socket_list; s = s->next){
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(s->transport == t || (s->peer && s->peer->transport == t)) {
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            local_socket_close_locked(s);
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto restart;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&socket_list_lock);
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int local_socket_enqueue(asocket *s, apacket *p)
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("LS(%d): enqueue %d\n", s->id, p->len);
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->ptr = p->data;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* if there is already data queue'd, we will receive
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** events when it's time to write.  just add this to
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** the tail
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(s->pkt_first) {
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto enqueue;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* write as much as we can, until we
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** would block or there is an error/eof
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(p->len > 0) {
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int r = adb_write(s->fd, p->ptr, p->len);
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(r > 0) {
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p->len -= r;
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p->ptr += r;
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if((r == 0) || (errno != EAGAIN)) {
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) );
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s->close(s);
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 1; /* not ready (error) */
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(p->len == 0) {
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(p);
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0; /* ready for more data */
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectenqueue:
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->next = 0;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(s->pkt_first) {
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_last->next = p;
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_first = p;
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->pkt_last = p;
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* make sure we are notified when we can drain the queue */
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_add(&s->fde, FDE_WRITE);
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1; /* not ready (backlog) */
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void local_socket_ready(asocket *s)
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* far side is ready for data, pay attention to
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           readable events */
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_add(&s->fde, FDE_READ);
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//    D("LS(%d): ready()\n", s->id);
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void local_socket_close(asocket *s)
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&socket_list_lock);
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    local_socket_close_locked(s);
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&socket_list_lock);
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// be sure to hold the socket list lock when calling this
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void local_socket_destroy(asocket  *s)
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p, *n;
202f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby    int exit_on_close = s->exit_on_close;
203f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby
204408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd);
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* IMPORTANT: the remove closes the fd
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** that belongs to this socket
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_remove(&s->fde);
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* dispose of any unwritten data */
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(p = s->pkt_first; p; p = n) {
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("LS(%d): discarding %d bytes\n", s->id, p->len);
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        n = p->next;
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(p);
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_socket(s);
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
219f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby
220f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby    if (exit_on_close) {
221f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby        D("local_socket_destroy: exiting\n");
222f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby        exit(1);
223f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby    }
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void local_socket_close_locked(asocket *s)
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
229408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("entered. LS(%d) fd=%d\n", s->id, s->fd);
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(s->peer) {
231408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
232408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          s->id, s->peer->id, s->peer->fd);
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = 0;
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // tweak to avoid deadlock
23549f1857dd8b64cdd57f28e965a1ff5fa0c2b0547Tom Marlin        if (s->peer->close == local_socket_close) {
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            local_socket_close_locked(s->peer);
23749f1857dd8b64cdd57f28e965a1ff5fa0c2b0547Tom Marlin        } else {
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s->peer->close(s->peer);
23949f1857dd8b64cdd57f28e965a1ff5fa0c2b0547Tom Marlin        }
24049f1857dd8b64cdd57f28e965a1ff5fa0c2b0547Tom Marlin        s->peer = 0;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* If we are already closing, or if there are no
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** pending packets, destroy immediately
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s->closing || s->pkt_first == NULL) {
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int   id = s->id;
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        local_socket_destroy(s);
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("LS(%d): closed\n", id);
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* otherwise, put on the closing list
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("LS(%d): closing\n", s->id);
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->closing = 1;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_del(&s->fde, FDE_READ);
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_socket(s);
259408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd);
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    insert_local_socket(s, &local_socket_closing_list);
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void local_socket_event_func(int fd, unsigned ev, void *_s)
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s = _s;
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
267408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);
268408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* put the FDE_WRITE processing before the FDE_READ
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ** in order to simplify the code.
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    */
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ev & FDE_WRITE){
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        apacket *p;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while((p = s->pkt_first) != 0) {
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            while(p->len > 0) {
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int r = adb_write(fd, p->ptr, p->len);
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(r > 0) {
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    p->ptr += r;
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    p->len -= r;
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    continue;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(r < 0) {
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* returning here is ok because FDE_READ will
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ** be processed in the next iteration loop
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    */
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if(errno == EAGAIN) return;
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if(errno == EINTR) continue;
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
2905b811fa5dd00288954f15209a56aea03d5e4a004Christopher Tate                D(" closing after write because r=%d and errno is %d\n", r, errno);
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->close(s);
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(p->len == 0) {
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->pkt_first = p->next;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(s->pkt_first == 0) s->pkt_last = 0;
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                put_apacket(p);
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* if we sent the last packet of a closing socket,
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** we can now destroy it.
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (s->closing) {
3065b811fa5dd00288954f15209a56aea03d5e4a004Christopher Tate            D(" closing because 'closing' is set after write\n");
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s->close(s);
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* no more packets queued, so we can ignore
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** writable events again and tell our peer
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** to resume writing
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_del(&s->fde, FDE_WRITE);
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->ready(s->peer);
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ev & FDE_READ){
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        apacket *p = get_apacket();
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        unsigned char *x = p->data;
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        size_t avail = MAX_PAYLOAD;
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int r;
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int is_eof = 0;
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while(avail > 0) {
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            r = adb_read(fd, x, avail);
329408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%d\n", s->id, s->fd, r, r<0?errno:0, avail);
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(r > 0) {
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                avail -= r;
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                x += r;
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                continue;
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(r < 0) {
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(errno == EAGAIN) break;
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(errno == EINTR) continue;
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* r = 0 or unhandled error */
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            is_eof = 1;
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
344408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n",
345408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          s->id, s->fd, r, is_eof, s->fde.force_eof);
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if((avail == MAX_PAYLOAD) || (s->peer == 0)) {
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            put_apacket(p);
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p->len = MAX_PAYLOAD - avail;
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            r = s->peer->enqueue(s->peer, p);
352408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r);
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(r < 0) {
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* error return means they closed us as a side-effect
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ** and we must return immediately.
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    **
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ** note that if we still have buffered packets, the
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ** socket will be placed on the closing socket list.
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ** this handler function will be called again
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ** to process FDE_WRITE events.
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    */
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(r > 0) {
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* if the remote cannot accept further events,
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ** we disable notification of READs.  They'll
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ** be enabled again when we get a call to ready()
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    */
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fdevent_del(&s->fde, FDE_READ);
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
374112445b8a752ce174f36cf853d5f1c356c3f5286JP Abgrall        /* Don't allow a forced eof if data is still there */
375112445b8a752ce174f36cf853d5f1c356c3f5286JP Abgrall        if((s->fde.force_eof && !r) || is_eof) {
3765b811fa5dd00288954f15209a56aea03d5e4a004Christopher Tate            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof);
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s->close(s);
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ev & FDE_ERROR){
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* this should be caught be the next read or write
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** catching it here means we may skip the last few
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** bytes of readable data.
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//        s->close(s);
387408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
388408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket *create_local_socket(int fd)
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s = calloc(1, sizeof(asocket));
396c419e2a210ad7e37a1f749f2ab4de7c7f95b90d7André Goddard Rosa    if (s == NULL) fatal("cannot allocate socket");
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->fd = fd;
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->enqueue = local_socket_enqueue;
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = local_socket_ready;
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = local_socket_close;
401408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    install_local_socket(s);
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_install(&s->fde, fd, local_socket_event_func, s);
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*    fdevent_add(&s->fde, FDE_ERROR); */
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //fprintf(stderr, "Created local socket in create_local_socket \n");
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("LS(%d): created (fd=%d)\n", s->id, s->fd);
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket *create_local_service_socket(const char *name)
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s;
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if !ADB_HOST
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strcmp(name,"jdwp")) {
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return create_jdwp_service_socket();
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strcmp(name,"track-jdwp")) {
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return create_jdwp_tracker_service_socket();
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = service_to_fd(name);
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) return 0;
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s = create_local_socket(fd);
427408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
428f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby
429f91259a8f0d75d721761d588a4b811427565c984JP Abgrall#if !ADB_HOST
430d7f1feb5c8c76838b822d093983cc8a3f57a9b2dJP Abgrall    if ((!strcmp(name, "root:") && getuid() != 0)
431d7f1feb5c8c76838b822d093983cc8a3f57a9b2dJP Abgrall        || !strcmp(name, "usb:")
432d7f1feb5c8c76838b822d093983cc8a3f57a9b2dJP Abgrall        || !strcmp(name, "tcpip:")) {
433f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby        D("LS(%d): enabling exit_on_close\n", s->id);
434f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby        s->exit_on_close = 1;
435f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby    }
436f91259a8f0d75d721761d588a4b811427565c984JP Abgrall#endif
437f366b3698b409405e1ee88476d1186f29fe14b06Benoit Goby
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic asocket *create_host_service_socket(const char *name, const char* serial)
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s;
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s = host_service_to_socket(name, serial);
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s != NULL) {
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("LS(%d) bound to '%s'\n", s->id, name);
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return s;
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* ADB_HOST */
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* a Remote socket is used to send/receive data to/from a given transport object
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** it needs to be closed when the transport is forcibly destroyed by the user
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct aremotesocket {
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket      socket;
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adisconnect  disconnect;
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} aremotesocket;
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int remote_socket_enqueue(asocket *s, apacket *p)
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
467408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n",
468408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      s->id, s->fd, s->peer->fd);
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_WRTE;
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = s->peer->id;
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = s->id;
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.data_length = p->len;
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void remote_socket_ready(asocket *s)
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
479408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n",
480408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      s->id, s->fd, s->peer->fd);
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p = get_apacket();
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_OKAY;
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = s->peer->id;
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = s->id;
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void remote_socket_close(asocket *s)
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
490408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n",
491408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      s->id, s->fd, s->peer?s->peer->fd:-1);
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p = get_apacket();
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_CLSE;
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(s->peer) {
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p->msg.arg0 = s->peer->id;
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = 0;
497408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n",
498408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          s->id, s->peer->id, s->peer->fd);
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->close(s->peer);
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = s->id;
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("RS(%d): closed\n", s->id);
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void remote_socket_disconnect(void*  _s, atransport*  t)
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket*  s    = _s;
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket*  peer = s->peer;
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("remote_socket_disconnect RS(%d)\n", s->id);
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (peer) {
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->peer = NULL;
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->close(peer);
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket *create_remote_socket(unsigned id, atransport *t)
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s = calloc(1, sizeof(aremotesocket));
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adisconnect*  dis = &((aremotesocket*)s)->disconnect;
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
527c419e2a210ad7e37a1f749f2ab4de7c7f95b90d7André Goddard Rosa    if (s == NULL) fatal("cannot allocate socket");
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->id = id;
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->enqueue = remote_socket_enqueue;
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = remote_socket_ready;
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = remote_socket_close;
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->transport = t;
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dis->func   = remote_socket_disconnect;
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dis->opaque = s;
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    add_transport_disconnect( t, dis );
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("RS(%d): created\n", s->id);
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid connect_to_remote(asocket *s, const char *destination)
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
543408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd);
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p = get_apacket();
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len = strlen(destination) + 1;
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(len > (MAX_PAYLOAD-1)) {
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fatal("destination oversized");
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("LS(%d): connect('%s')\n", s->id, destination);
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_OPEN;
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = s->id;
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.data_length = len;
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strcpy((char*) p->data, destination);
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, s->transport);
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* this is used by magic sockets to rig local sockets to
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   send the go-ahead message when they connect */
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void local_socket_ready_notify(asocket *s)
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = local_socket_ready;
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = local_socket_close;
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_write(s->fd, "OKAY", 4);
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready(s);
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* this is used by magic sockets to rig local sockets to
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   send the failure message if they are closed before
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   connected (to avoid closing them without a status message) */
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void local_socket_close_notify(asocket *s)
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = local_socket_ready;
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = local_socket_close;
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sendfailmsg(s->fd, "closed");
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close(s);
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunsigned unhex(unsigned char *s, int len)
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned n = 0, c;
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(len-- > 0) {
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        switch((c = *s++)) {
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '0': case '1': case '2':
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '3': case '4': case '5':
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '6': case '7': case '8':
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '9':
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c -= '0';
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'a': case 'b': case 'c':
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'd': case 'e': case 'f':
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c = c - 'a' + 10;
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'A': case 'B': case 'C':
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'D': case 'E': case 'F':
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c = c - 'A' + 10;
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        default:
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0xffffffff;
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        n = (n << 4) | c;
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return n;
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
61128e1390e688f721e13a9877d3c41884bf151db60Terence Haddock/* skip_host_serial return the position in a string
61228e1390e688f721e13a9877d3c41884bf151db60Terence Haddock   skipping over the 'serial' parameter in the ADB protocol,
61328e1390e688f721e13a9877d3c41884bf151db60Terence Haddock   where parameter string may be a host:port string containing
61428e1390e688f721e13a9877d3c41884bf151db60Terence Haddock   the protocol delimiter (colon). */
61528e1390e688f721e13a9877d3c41884bf151db60Terence Haddockchar *skip_host_serial(char *service) {
61628e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    char *first_colon, *serial_end;
61728e1390e688f721e13a9877d3c41884bf151db60Terence Haddock
61828e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    first_colon = strchr(service, ':');
61928e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    if (!first_colon) {
62028e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        /* No colon in service string. */
62128e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        return NULL;
62228e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    }
62328e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    serial_end = first_colon;
62428e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    if (isdigit(serial_end[1])) {
62528e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        serial_end++;
62628e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        while ((*serial_end) && isdigit(*serial_end)) {
62728e1390e688f721e13a9877d3c41884bf151db60Terence Haddock            serial_end++;
62828e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        }
62928e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        if ((*serial_end) != ':') {
63028e1390e688f721e13a9877d3c41884bf151db60Terence Haddock            // Something other than numbers was found, reset the end.
63128e1390e688f721e13a9877d3c41884bf151db60Terence Haddock            serial_end = first_colon;
63228e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        }
63328e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    }
63428e1390e688f721e13a9877d3c41884bf151db60Terence Haddock    return serial_end;
63528e1390e688f721e13a9877d3c41884bf151db60Terence Haddock}
63628e1390e688f721e13a9877d3c41884bf151db60Terence Haddock
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int smart_socket_enqueue(asocket *s, apacket *p)
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned len;
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *service = NULL;
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* serial = NULL;
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    transport_type ttype = kTransportAny;
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("SS(%d): enqueue %d\n", s->id, p->len);
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(s->pkt_first == 0) {
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_first = p;
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_last = p;
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if((s->pkt_first->len + p->len) > MAX_PAYLOAD) {
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("SS(%d): overflow\n", s->id);
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            put_apacket(p);
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memcpy(s->pkt_first->data + s->pkt_first->len,
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               p->data, p->len);
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->pkt_first->len += p->len;
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(p);
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p = s->pkt_first;
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* don't bother if we can't decode the length */
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(p->len < 4) return 0;
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = unhex(p->data, 4);
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((len < 1) ||  (len > 1024)) {
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("SS(%d): bad size (%d)\n", s->id, len);
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("SS(%d): len is %d\n", s->id, len );
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* can't do anything until we have the full header */
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((len + 4) > p->len) {
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len);
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->data[len + 4] = 0;
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4));
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    service = (char *)p->data + 4;
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strncmp(service, "host-serial:", strlen("host-serial:"))) {
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char* serial_end;
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host-serial:");
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
69228e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        // serial number should follow "host:" and could be a host:port string.
69328e1390e688f721e13a9877d3c41884bf151db60Terence Haddock        serial_end = skip_host_serial(service);
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (serial_end) {
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *serial_end = 0; // terminate string
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            serial = service;
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            service = serial_end + 1;
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ttype = kTransportUsb;
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host-usb:");
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(service, "host-local:", strlen("host-local:"))) {
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ttype = kTransportLocal;
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host-local:");
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(service, "host:", strlen("host:"))) {
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ttype = kTransportAny;
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service += strlen("host:");
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        service = NULL;
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (service) {
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        asocket *s2;
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* some requests are handled immediately -- in that
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** case the handle_host_request() routine has sent
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** the OKAY or FAIL message and all we have to do
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** is clean up.
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) {
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* XXX fail message? */
722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D( "SS(%d): handled host service '%s'\n", s->id, service );
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strncmp(service, "transport", strlen("transport"))) {
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D( "SS(%d): okay transport\n", s->id );
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p->len = 0;
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* try to find a local service with this name.
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** if no such service exists, we'll fail out
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** and tear down here.
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s2 = create_host_service_socket(service, serial);
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(s2 == 0) {
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D( "SS(%d): couldn't create host service '%s'\n", s->id, service );
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sendfailmsg(s->peer->fd, "unknown host service");
739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we've connected to a local host service,
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** so we make our peer back into a regular
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** local socket and bind it to the new local
745dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** service socket, acknowledge the successful
746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** connection, and close this smart socket now
747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** that its work is done.
748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
749dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_write(s->peer->fd, "OKAY", 4);
750dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
751dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->ready = local_socket_ready;
752dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->close = local_socket_close;
753dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = s2;
754dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s2->peer = s->peer;
755dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer = 0;
756dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D( "SS(%d): okay\n", s->id );
757dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->close(s);
758dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
759dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* initial state is "ready" */
760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s2->ready(s2);
761dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
762dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /* !ADB_HOST */
764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s->transport == NULL) {
765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char* error_string = "unknown failure";
766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->transport = acquire_one_transport (CS_ANY,
767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kTransportAny, NULL, &error_string);
768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (s->transport == NULL) {
770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sendfailmsg(s->peer->fd, error_string);
771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) {
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           /* if there's no remote we fail the connection
778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** right here and terminate it
779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sendfailmsg(s->peer->fd, "device offline (x)");
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* instrument our peer to pass the success or fail
786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** message back once it connects or closes, then
787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** detach from it, request the connection, and
788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** tear down
789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->ready = local_socket_ready_notify;
791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->close = local_socket_close_notify;
792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->peer = 0;
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* give him our transport and upref it */
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->transport = s->transport;
795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    connect_to_remote(s->peer, (char*) (p->data + 4));
797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer = 0;
798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close(s);
799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* we're going to close our peer as a side-effect, so
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** return -1 to signal that state to the local socket
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** who is enqueueing against us
805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close(s);
807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void smart_socket_ready(asocket *s)
811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("SS(%d): ready\n", s->id);
813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
814dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void smart_socket_close(asocket *s)
816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
817dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("SS(%d): closed\n", s->id);
818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(s->pkt_first){
819dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        put_apacket(s->pkt_first);
820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
821dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(s->peer) {
822dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->peer = 0;
823dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->close(s->peer);
82449f1857dd8b64cdd57f28e965a1ff5fa0c2b0547Tom Marlin        s->peer = 0;
825dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
826dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
827dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
828dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act))
830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
831dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Creating smart socket \n");
832dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s = calloc(1, sizeof(asocket));
833c419e2a210ad7e37a1f749f2ab4de7c7f95b90d7André Goddard Rosa    if (s == NULL) fatal("cannot allocate socket");
834dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->enqueue = smart_socket_enqueue;
835dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready = smart_socket_ready;
836dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->close = smart_socket_close;
837dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->extra = action_cb;
838dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("SS(%d): created %p\n", s->id, action_cb);
840dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
841dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
842dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
843dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid smart_socket_action(asocket *s, const char *act)
844dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
848dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid connect_to_smartsocket(asocket *s)
849dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Connecting to smart socket \n");
851dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *ss = create_smart_socket(smart_socket_action);
852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer = ss;
853dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ss->peer = s;
854dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->ready(s);
855dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
856