diff options
author | Dan Albert | 2015-02-19 15:21:14 -0600 |
---|---|---|
committer | Dan Albert | 2015-02-19 17:41:35 -0600 |
commit | f3a5726919ce35d3f5e628e9561496470195ac1f (patch) | |
tree | 247e812a898020502652e1cae9f244acab0aa517 /minadbd | |
parent | 4eb6c71e7f013e684828ae6216f61b83be552282 (diff) | |
download | platform-bootable-recovery-f3a5726919ce35d3f5e628e9561496470195ac1f.tar.gz platform-bootable-recovery-f3a5726919ce35d3f5e628e9561496470195ac1f.tar.xz platform-bootable-recovery-f3a5726919ce35d3f5e628e9561496470195ac1f.zip |
Kill of most of the remainder of minadbd.
I think everything left now is here to stay (services.c might get
massaged in to libadbd if it gets refactored).
Bug: 17626262
Change-Id: I01faf8b277a601a40e3a0f4c3b8206c97f1d2ce6
Diffstat (limited to 'minadbd')
-rw-r--r-- | minadbd/Android.mk | 3 | ||||
-rw-r--r-- | minadbd/README.txt | 37 | ||||
-rw-r--r-- | minadbd/adb.c | 372 | ||||
-rw-r--r-- | minadbd/adb.h | 433 | ||||
-rw-r--r-- | minadbd/adb_main.c | 4 | ||||
-rw-r--r-- | minadbd/sockets.c | 731 |
6 files changed, 7 insertions, 1573 deletions
diff --git a/minadbd/Android.mk b/minadbd/Android.mk index 0cba0c5f..f4b060b4 100644 --- a/minadbd/Android.mk +++ b/minadbd/Android.mk | |||
@@ -11,15 +11,14 @@ LOCAL_PATH:= $(call my-dir) | |||
11 | include $(CLEAR_VARS) | 11 | include $(CLEAR_VARS) |
12 | 12 | ||
13 | LOCAL_SRC_FILES := \ | 13 | LOCAL_SRC_FILES := \ |
14 | adb.c \ | ||
15 | adb_main.c \ | 14 | adb_main.c \ |
16 | fuse_adb_provider.c \ | 15 | fuse_adb_provider.c \ |
17 | sockets.c \ | ||
18 | services.c \ | 16 | services.c \ |
19 | 17 | ||
20 | LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter | 18 | LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter |
21 | LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE | 19 | LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE |
22 | LOCAL_C_INCLUDES := bootable/recovery system/core/adb | 20 | LOCAL_C_INCLUDES := bootable/recovery system/core/adb |
21 | LOCAL_WHOLE_STATIC_LIBRARIES := libadbd | ||
23 | 22 | ||
24 | LOCAL_MODULE := libminadbd | 23 | LOCAL_MODULE := libminadbd |
25 | 24 | ||
diff --git a/minadbd/README.txt b/minadbd/README.txt index c9df484c..e69dc87c 100644 --- a/minadbd/README.txt +++ b/minadbd/README.txt | |||
@@ -1,39 +1,8 @@ | |||
1 | The contents of this directory are copied from system/core/adb, with | 1 | minadbd is now mostly built from libadbd. The fuse features are unique to |
2 | the following changes: | 2 | minadbd, and services.c has been modified as follows: |
3 | 3 | ||
4 | adb.c | 4 | - all services removed |
5 | - much support for host mode and non-linux OS's stripped out; this | ||
6 | version only runs as adbd on the device. | ||
7 | - always setuid/setgid's itself to the shell user | ||
8 | - only uses USB transport | ||
9 | - references to JDWP removed | ||
10 | - main() removed | ||
11 | - all ADB_HOST and win32 code removed | ||
12 | - removed listeners, logging code, background server (for host) | ||
13 | |||
14 | adb.h | ||
15 | - minor changes to match adb.c changes | ||
16 | |||
17 | sockets.c | ||
18 | - references to JDWP removed | ||
19 | - ADB_HOST code removed | ||
20 | |||
21 | services.c | ||
22 | - all services except echo_service (which is commented out) removed | ||
23 | - all host mode support removed | 5 | - all host mode support removed |
24 | - sideload_service() added; this is the only service supported. It | 6 | - sideload_service() added; this is the only service supported. It |
25 | receives a single blob of data, writes it to a fixed filename, and | 7 | receives a single blob of data, writes it to a fixed filename, and |
26 | makes the process exit. | 8 | makes the process exit. |
27 | |||
28 | Android.mk | ||
29 | - only builds in adbd mode; builds as static library instead of a | ||
30 | standalone executable. | ||
31 | |||
32 | sysdeps.h | ||
33 | - changes adb_creat() to use O_NOFOLLOW | ||
34 | |||
35 | transport.c | ||
36 | - removed ADB_HOST code | ||
37 | |||
38 | transport_usb.c | ||
39 | - removed ADB_HOST code | ||
diff --git a/minadbd/adb.c b/minadbd/adb.c deleted file mode 100644 index 5f9cfdfa..00000000 --- a/minadbd/adb.c +++ /dev/null | |||
@@ -1,372 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #define TRACE_TAG TRACE_ADB | ||
18 | |||
19 | #include <stdio.h> | ||
20 | #include <stdlib.h> | ||
21 | #include <ctype.h> | ||
22 | #include <stdarg.h> | ||
23 | #include <errno.h> | ||
24 | #include <string.h> | ||
25 | #include <time.h> | ||
26 | #include <sys/time.h> | ||
27 | |||
28 | #include "sysdeps.h" | ||
29 | #include "adb.h" | ||
30 | |||
31 | #include <private/android_filesystem_config.h> | ||
32 | |||
33 | #if ADB_TRACE | ||
34 | ADB_MUTEX_DEFINE( D_lock ); | ||
35 | #endif | ||
36 | |||
37 | int HOST = 0; | ||
38 | |||
39 | static const char *adb_device_banner = "sideload"; | ||
40 | |||
41 | void fatal(const char *fmt, ...) | ||
42 | { | ||
43 | va_list ap; | ||
44 | va_start(ap, fmt); | ||
45 | fprintf(stderr, "error: "); | ||
46 | vfprintf(stderr, fmt, ap); | ||
47 | fprintf(stderr, "\n"); | ||
48 | va_end(ap); | ||
49 | exit(-1); | ||
50 | } | ||
51 | |||
52 | void fatal_errno(const char *fmt, ...) | ||
53 | { | ||
54 | va_list ap; | ||
55 | va_start(ap, fmt); | ||
56 | fprintf(stderr, "error: %s: ", strerror(errno)); | ||
57 | vfprintf(stderr, fmt, ap); | ||
58 | fprintf(stderr, "\n"); | ||
59 | va_end(ap); | ||
60 | exit(-1); | ||
61 | } | ||
62 | |||
63 | int adb_trace_mask; | ||
64 | |||
65 | /* read a comma/space/colum/semi-column separated list of tags | ||
66 | * from the ADB_TRACE environment variable and build the trace | ||
67 | * mask from it. note that '1' and 'all' are special cases to | ||
68 | * enable all tracing | ||
69 | */ | ||
70 | void adb_trace_init(void) | ||
71 | { | ||
72 | const char* p = getenv("ADB_TRACE"); | ||
73 | const char* q; | ||
74 | |||
75 | static const struct { | ||
76 | const char* tag; | ||
77 | int flag; | ||
78 | } tags[] = { | ||
79 | { "1", 0 }, | ||
80 | { "all", 0 }, | ||
81 | { "adb", TRACE_ADB }, | ||
82 | { "sockets", TRACE_SOCKETS }, | ||
83 | { "packets", TRACE_PACKETS }, | ||
84 | { "rwx", TRACE_RWX }, | ||
85 | { "usb", TRACE_USB }, | ||
86 | { "sync", TRACE_SYNC }, | ||
87 | { "sysdeps", TRACE_SYSDEPS }, | ||
88 | { "transport", TRACE_TRANSPORT }, | ||
89 | { "jdwp", TRACE_JDWP }, | ||
90 | { "services", TRACE_SERVICES }, | ||
91 | { NULL, 0 } | ||
92 | }; | ||
93 | |||
94 | if (p == NULL) | ||
95 | return; | ||
96 | |||
97 | /* use a comma/column/semi-colum/space separated list */ | ||
98 | while (*p) { | ||
99 | int len, tagn; | ||
100 | |||
101 | q = strpbrk(p, " ,:;"); | ||
102 | if (q == NULL) { | ||
103 | q = p + strlen(p); | ||
104 | } | ||
105 | len = q - p; | ||
106 | |||
107 | for (tagn = 0; tags[tagn].tag != NULL; tagn++) | ||
108 | { | ||
109 | int taglen = strlen(tags[tagn].tag); | ||
110 | |||
111 | if (len == taglen && !memcmp(tags[tagn].tag, p, len) ) | ||
112 | { | ||
113 | int flag = tags[tagn].flag; | ||
114 | if (flag == 0) { | ||
115 | adb_trace_mask = ~0; | ||
116 | return; | ||
117 | } | ||
118 | adb_trace_mask |= (1 << flag); | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | p = q; | ||
123 | if (*p) | ||
124 | p++; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | |||
129 | apacket *get_apacket(void) | ||
130 | { | ||
131 | apacket *p = malloc(sizeof(apacket)); | ||
132 | if(p == 0) fatal("failed to allocate an apacket"); | ||
133 | memset(p, 0, sizeof(apacket) - MAX_PAYLOAD); | ||
134 | return p; | ||
135 | } | ||
136 | |||
137 | void put_apacket(apacket *p) | ||
138 | { | ||
139 | free(p); | ||
140 | } | ||
141 | |||
142 | void handle_online(void) | ||
143 | { | ||
144 | D("adb: online\n"); | ||
145 | } | ||
146 | |||
147 | void handle_offline(atransport *t) | ||
148 | { | ||
149 | D("adb: offline\n"); | ||
150 | //Close the associated usb | ||
151 | run_transport_disconnects(t); | ||
152 | } | ||
153 | |||
154 | #if TRACE_PACKETS | ||
155 | #define DUMPMAX 32 | ||
156 | void print_packet(const char *label, apacket *p) | ||
157 | { | ||
158 | char *tag; | ||
159 | char *x; | ||
160 | unsigned count; | ||
161 | |||
162 | switch(p->msg.command){ | ||
163 | case A_SYNC: tag = "SYNC"; break; | ||
164 | case A_CNXN: tag = "CNXN" ; break; | ||
165 | case A_OPEN: tag = "OPEN"; break; | ||
166 | case A_OKAY: tag = "OKAY"; break; | ||
167 | case A_CLSE: tag = "CLSE"; break; | ||
168 | case A_WRTE: tag = "WRTE"; break; | ||
169 | default: tag = "????"; break; | ||
170 | } | ||
171 | |||
172 | fprintf(stderr, "%s: %s %08x %08x %04x \"", | ||
173 | label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length); | ||
174 | count = p->msg.data_length; | ||
175 | x = (char*) p->data; | ||
176 | if(count > DUMPMAX) { | ||
177 | count = DUMPMAX; | ||
178 | tag = "\n"; | ||
179 | } else { | ||
180 | tag = "\"\n"; | ||
181 | } | ||
182 | while(count-- > 0){ | ||
183 | if((*x >= ' ') && (*x < 127)) { | ||
184 | fputc(*x, stderr); | ||
185 | } else { | ||
186 | fputc('.', stderr); | ||
187 | } | ||
188 | x++; | ||
189 | } | ||
190 | fprintf(stderr, tag); | ||
191 | } | ||
192 | #endif | ||
193 | |||
194 | static void send_ready(unsigned local, unsigned remote, atransport *t) | ||
195 | { | ||
196 | D("Calling send_ready \n"); | ||
197 | apacket *p = get_apacket(); | ||
198 | p->msg.command = A_OKAY; | ||
199 | p->msg.arg0 = local; | ||
200 | p->msg.arg1 = remote; | ||
201 | send_packet(p, t); | ||
202 | } | ||
203 | |||
204 | static void send_close(unsigned local, unsigned remote, atransport *t) | ||
205 | { | ||
206 | D("Calling send_close \n"); | ||
207 | apacket *p = get_apacket(); | ||
208 | p->msg.command = A_CLSE; | ||
209 | p->msg.arg0 = local; | ||
210 | p->msg.arg1 = remote; | ||
211 | send_packet(p, t); | ||
212 | } | ||
213 | |||
214 | static void send_connect(atransport *t) | ||
215 | { | ||
216 | D("Calling send_connect \n"); | ||
217 | apacket *cp = get_apacket(); | ||
218 | cp->msg.command = A_CNXN; | ||
219 | cp->msg.arg0 = A_VERSION; | ||
220 | cp->msg.arg1 = MAX_PAYLOAD; | ||
221 | snprintf((char*) cp->data, sizeof cp->data, "%s::", | ||
222 | HOST ? "host" : adb_device_banner); | ||
223 | cp->msg.data_length = strlen((char*) cp->data) + 1; | ||
224 | send_packet(cp, t); | ||
225 | } | ||
226 | |||
227 | void parse_banner(char *banner, atransport *t) | ||
228 | { | ||
229 | char *type, *product, *end; | ||
230 | |||
231 | D("parse_banner: %s\n", banner); | ||
232 | type = banner; | ||
233 | product = strchr(type, ':'); | ||
234 | if(product) { | ||
235 | *product++ = 0; | ||
236 | } else { | ||
237 | product = ""; | ||
238 | } | ||
239 | |||
240 | /* remove trailing ':' */ | ||
241 | end = strchr(product, ':'); | ||
242 | if(end) *end = 0; | ||
243 | |||
244 | /* save product name in device structure */ | ||
245 | if (t->product == NULL) { | ||
246 | t->product = strdup(product); | ||
247 | } else if (strcmp(product, t->product) != 0) { | ||
248 | free(t->product); | ||
249 | t->product = strdup(product); | ||
250 | } | ||
251 | |||
252 | if(!strcmp(type, "bootloader")){ | ||
253 | D("setting connection_state to CS_BOOTLOADER\n"); | ||
254 | t->connection_state = CS_BOOTLOADER; | ||
255 | update_transports(); | ||
256 | return; | ||
257 | } | ||
258 | |||
259 | if(!strcmp(type, "device")) { | ||
260 | D("setting connection_state to CS_DEVICE\n"); | ||
261 | t->connection_state = CS_DEVICE; | ||
262 | update_transports(); | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | if(!strcmp(type, "recovery")) { | ||
267 | D("setting connection_state to CS_RECOVERY\n"); | ||
268 | t->connection_state = CS_RECOVERY; | ||
269 | update_transports(); | ||
270 | return; | ||
271 | } | ||
272 | |||
273 | if(!strcmp(type, "sideload")) { | ||
274 | D("setting connection_state to CS_SIDELOAD\n"); | ||
275 | t->connection_state = CS_SIDELOAD; | ||
276 | update_transports(); | ||
277 | return; | ||
278 | } | ||
279 | |||
280 | t->connection_state = CS_HOST; | ||
281 | } | ||
282 | |||
283 | void handle_packet(apacket *p, atransport *t) | ||
284 | { | ||
285 | asocket *s; | ||
286 | |||
287 | D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0], | ||
288 | ((char*) (&(p->msg.command)))[1], | ||
289 | ((char*) (&(p->msg.command)))[2], | ||
290 | ((char*) (&(p->msg.command)))[3]); | ||
291 | print_packet("recv", p); | ||
292 | |||
293 | switch(p->msg.command){ | ||
294 | case A_SYNC: | ||
295 | if(p->msg.arg0){ | ||
296 | send_packet(p, t); | ||
297 | if(HOST) send_connect(t); | ||
298 | } else { | ||
299 | t->connection_state = CS_OFFLINE; | ||
300 | handle_offline(t); | ||
301 | send_packet(p, t); | ||
302 | } | ||
303 | return; | ||
304 | |||
305 | case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */ | ||
306 | /* XXX verify version, etc */ | ||
307 | if(t->connection_state != CS_OFFLINE) { | ||
308 | t->connection_state = CS_OFFLINE; | ||
309 | handle_offline(t); | ||
310 | } | ||
311 | parse_banner((char*) p->data, t); | ||
312 | handle_online(); | ||
313 | if(!HOST) send_connect(t); | ||
314 | break; | ||
315 | |||
316 | case A_OPEN: /* OPEN(local-id, 0, "destination") */ | ||
317 | if(t->connection_state != CS_OFFLINE) { | ||
318 | char *name = (char*) p->data; | ||
319 | name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; | ||
320 | s = create_local_service_socket(name); | ||
321 | if(s == 0) { | ||
322 | send_close(0, p->msg.arg0, t); | ||
323 | } else { | ||
324 | s->peer = create_remote_socket(p->msg.arg0, t); | ||
325 | s->peer->peer = s; | ||
326 | send_ready(s->id, s->peer->id, t); | ||
327 | s->ready(s); | ||
328 | } | ||
329 | } | ||
330 | break; | ||
331 | |||
332 | case A_OKAY: /* READY(local-id, remote-id, "") */ | ||
333 | if(t->connection_state != CS_OFFLINE) { | ||
334 | if((s = find_local_socket(p->msg.arg1))) { | ||
335 | if(s->peer == 0) { | ||
336 | s->peer = create_remote_socket(p->msg.arg0, t); | ||
337 | s->peer->peer = s; | ||
338 | } | ||
339 | s->ready(s); | ||
340 | } | ||
341 | } | ||
342 | break; | ||
343 | |||
344 | case A_CLSE: /* CLOSE(local-id, remote-id, "") */ | ||
345 | if(t->connection_state != CS_OFFLINE) { | ||
346 | if((s = find_local_socket(p->msg.arg1))) { | ||
347 | s->close(s); | ||
348 | } | ||
349 | } | ||
350 | break; | ||
351 | |||
352 | case A_WRTE: | ||
353 | if(t->connection_state != CS_OFFLINE) { | ||
354 | if((s = find_local_socket(p->msg.arg1))) { | ||
355 | unsigned rid = p->msg.arg0; | ||
356 | p->len = p->msg.data_length; | ||
357 | |||
358 | if(s->enqueue(s, p) == 0) { | ||
359 | D("Enqueue the socket\n"); | ||
360 | send_ready(s->id, rid, t); | ||
361 | } | ||
362 | return; | ||
363 | } | ||
364 | } | ||
365 | break; | ||
366 | |||
367 | default: | ||
368 | printf("handle_packet: what is %08x?!\n", p->msg.command); | ||
369 | } | ||
370 | |||
371 | put_apacket(p); | ||
372 | } | ||
diff --git a/minadbd/adb.h b/minadbd/adb.h deleted file mode 100644 index 58818a99..00000000 --- a/minadbd/adb.h +++ /dev/null | |||
@@ -1,433 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef __ADB_H | ||
18 | #define __ADB_H | ||
19 | |||
20 | #include <limits.h> | ||
21 | |||
22 | #include "transport.h" /* readx(), writex() */ | ||
23 | #include "fdevent.h" | ||
24 | |||
25 | #ifdef __cplusplus | ||
26 | extern "C" { | ||
27 | #endif | ||
28 | |||
29 | #define MAX_PAYLOAD 4096 | ||
30 | |||
31 | #define A_SYNC 0x434e5953 | ||
32 | #define A_CNXN 0x4e584e43 | ||
33 | #define A_OPEN 0x4e45504f | ||
34 | #define A_OKAY 0x59414b4f | ||
35 | #define A_CLSE 0x45534c43 | ||
36 | #define A_WRTE 0x45545257 | ||
37 | |||
38 | #define A_VERSION 0x01000000 // ADB protocol version | ||
39 | |||
40 | #define ADB_VERSION_MAJOR 1 // Used for help/version information | ||
41 | #define ADB_VERSION_MINOR 0 // Used for help/version information | ||
42 | |||
43 | #define ADB_SERVER_VERSION 29 // Increment this when we want to force users to start a new adb server | ||
44 | |||
45 | typedef struct amessage amessage; | ||
46 | typedef struct apacket apacket; | ||
47 | typedef struct asocket asocket; | ||
48 | typedef struct aservice aservice; | ||
49 | typedef struct atransport atransport; | ||
50 | typedef struct adisconnect adisconnect; | ||
51 | typedef struct usb_handle usb_handle; | ||
52 | |||
53 | struct amessage { | ||
54 | unsigned command; /* command identifier constant */ | ||
55 | unsigned arg0; /* first argument */ | ||
56 | unsigned arg1; /* second argument */ | ||
57 | unsigned data_length; /* length of payload (0 is allowed) */ | ||
58 | unsigned data_check; /* checksum of data payload */ | ||
59 | unsigned magic; /* command ^ 0xffffffff */ | ||
60 | }; | ||
61 | |||
62 | struct apacket | ||
63 | { | ||
64 | apacket *next; | ||
65 | |||
66 | unsigned len; | ||
67 | unsigned char *ptr; | ||
68 | |||
69 | amessage msg; | ||
70 | unsigned char data[MAX_PAYLOAD]; | ||
71 | }; | ||
72 | |||
73 | /* An asocket represents one half of a connection between a local and | ||
74 | ** remote entity. A local asocket is bound to a file descriptor. A | ||
75 | ** remote asocket is bound to the protocol engine. | ||
76 | */ | ||
77 | struct asocket { | ||
78 | /* chain pointers for the local/remote list of | ||
79 | ** asockets that this asocket lives in | ||
80 | */ | ||
81 | asocket *next; | ||
82 | asocket *prev; | ||
83 | |||
84 | /* the unique identifier for this asocket | ||
85 | */ | ||
86 | unsigned id; | ||
87 | |||
88 | /* flag: set when the socket's peer has closed | ||
89 | ** but packets are still queued for delivery | ||
90 | */ | ||
91 | int closing; | ||
92 | |||
93 | /* the asocket we are connected to | ||
94 | */ | ||
95 | |||
96 | asocket *peer; | ||
97 | |||
98 | /* For local asockets, the fde is used to bind | ||
99 | ** us to our fd event system. For remote asockets | ||
100 | ** these fields are not used. | ||
101 | */ | ||
102 | fdevent fde; | ||
103 | int fd; | ||
104 | |||
105 | /* queue of apackets waiting to be written | ||
106 | */ | ||
107 | apacket *pkt_first; | ||
108 | apacket *pkt_last; | ||
109 | |||
110 | /* enqueue is called by our peer when it has data | ||
111 | ** for us. It should return 0 if we can accept more | ||
112 | ** data or 1 if not. If we return 1, we must call | ||
113 | ** peer->ready() when we once again are ready to | ||
114 | ** receive data. | ||
115 | */ | ||
116 | int (*enqueue)(asocket *s, apacket *pkt); | ||
117 | |||
118 | /* ready is called by the peer when it is ready for | ||
119 | ** us to send data via enqueue again | ||
120 | */ | ||
121 | void (*ready)(asocket *s); | ||
122 | |||
123 | /* close is called by the peer when it has gone away. | ||
124 | ** we are not allowed to make any further calls on the | ||
125 | ** peer once our close method is called. | ||
126 | */ | ||
127 | void (*close)(asocket *s); | ||
128 | |||
129 | /* socket-type-specific extradata */ | ||
130 | void *extra; | ||
131 | |||
132 | /* A socket is bound to atransport */ | ||
133 | atransport *transport; | ||
134 | }; | ||
135 | |||
136 | |||
137 | /* the adisconnect structure is used to record a callback that | ||
138 | ** will be called whenever a transport is disconnected (e.g. by the user) | ||
139 | ** this should be used to cleanup objects that depend on the | ||
140 | ** transport (e.g. remote sockets, etc...) | ||
141 | */ | ||
142 | struct adisconnect | ||
143 | { | ||
144 | void (*func)(void* opaque, atransport* t); | ||
145 | void* opaque; | ||
146 | adisconnect* next; | ||
147 | adisconnect* prev; | ||
148 | }; | ||
149 | |||
150 | |||
151 | /* a transport object models the connection to a remote device or emulator | ||
152 | ** there is one transport per connected device/emulator. a "local transport" | ||
153 | ** connects through TCP (for the emulator), while a "usb transport" through | ||
154 | ** USB (for real devices) | ||
155 | ** | ||
156 | ** note that kTransportHost doesn't really correspond to a real transport | ||
157 | ** object, it's a special value used to indicate that a client wants to | ||
158 | ** connect to a service implemented within the ADB server itself. | ||
159 | */ | ||
160 | typedef enum transport_type { | ||
161 | kTransportUsb, | ||
162 | kTransportLocal, | ||
163 | kTransportAny, | ||
164 | kTransportHost, | ||
165 | } transport_type; | ||
166 | |||
167 | struct atransport | ||
168 | { | ||
169 | atransport *next; | ||
170 | atransport *prev; | ||
171 | |||
172 | int (*read_from_remote)(apacket *p, atransport *t); | ||
173 | int (*write_to_remote)(apacket *p, atransport *t); | ||
174 | void (*close)(atransport *t); | ||
175 | void (*kick)(atransport *t); | ||
176 | |||
177 | int fd; | ||
178 | int transport_socket; | ||
179 | fdevent transport_fde; | ||
180 | int ref_count; | ||
181 | unsigned sync_token; | ||
182 | int connection_state; | ||
183 | transport_type type; | ||
184 | |||
185 | /* usb handle or socket fd as needed */ | ||
186 | usb_handle *usb; | ||
187 | int sfd; | ||
188 | |||
189 | /* used to identify transports for clients */ | ||
190 | char *serial; | ||
191 | char *product; | ||
192 | int adb_port; // Use for emulators (local transport) | ||
193 | |||
194 | /* a list of adisconnect callbacks called when the transport is kicked */ | ||
195 | int kicked; | ||
196 | adisconnect disconnects; | ||
197 | }; | ||
198 | |||
199 | |||
200 | void print_packet(const char *label, apacket *p); | ||
201 | |||
202 | asocket *find_local_socket(unsigned id); | ||
203 | void install_local_socket(asocket *s); | ||
204 | void remove_socket(asocket *s); | ||
205 | void close_all_sockets(atransport *t); | ||
206 | |||
207 | #define LOCAL_CLIENT_PREFIX "emulator-" | ||
208 | |||
209 | asocket *create_local_socket(int fd); | ||
210 | asocket *create_local_service_socket(const char *destination); | ||
211 | |||
212 | asocket *create_remote_socket(unsigned id, atransport *t); | ||
213 | void connect_to_remote(asocket *s, const char *destination); | ||
214 | void connect_to_smartsocket(asocket *s); | ||
215 | |||
216 | void fatal(const char *fmt, ...); | ||
217 | void fatal_errno(const char *fmt, ...); | ||
218 | |||
219 | void handle_packet(apacket *p, atransport *t); | ||
220 | void send_packet(apacket *p, atransport *t); | ||
221 | |||
222 | void get_my_path(char *s, size_t maxLen); | ||
223 | int launch_server(int server_port); | ||
224 | int adb_main(); | ||
225 | |||
226 | |||
227 | /* transports are ref-counted | ||
228 | ** get_device_transport does an acquire on your behalf before returning | ||
229 | */ | ||
230 | void init_transport_registration(void); | ||
231 | int list_transports(char *buf, size_t bufsize); | ||
232 | void update_transports(void); | ||
233 | |||
234 | asocket* create_device_tracker(void); | ||
235 | |||
236 | /* Obtain a transport from the available transports. | ||
237 | ** If state is != CS_ANY, only transports in that state are considered. | ||
238 | ** If serial is non-NULL then only the device with that serial will be chosen. | ||
239 | ** If no suitable transport is found, error is set. | ||
240 | */ | ||
241 | atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char **error_out); | ||
242 | void add_transport_disconnect( atransport* t, adisconnect* dis ); | ||
243 | void remove_transport_disconnect( atransport* t, adisconnect* dis ); | ||
244 | void run_transport_disconnects( atransport* t ); | ||
245 | void kick_transport( atransport* t ); | ||
246 | |||
247 | /* initialize a transport object's func pointers and state */ | ||
248 | #if ADB_HOST | ||
249 | int get_available_local_transport_index(); | ||
250 | #endif | ||
251 | void init_usb_transport(atransport *t, usb_handle *usb, int state); | ||
252 | |||
253 | /* for MacOS X cleanup */ | ||
254 | void close_usb_devices(); | ||
255 | |||
256 | /* these should only be used for the "adb disconnect" command */ | ||
257 | void unregister_transport(atransport *t); | ||
258 | void unregister_all_tcp_transports(); | ||
259 | |||
260 | void register_usb_transport(usb_handle *h, const char *serial, | ||
261 | const char* dev_path, unsigned writeable); | ||
262 | |||
263 | /* this should only be used for transports with connection_state == CS_NOPERM */ | ||
264 | void unregister_usb_transport(usb_handle *usb); | ||
265 | |||
266 | atransport *find_transport(const char *serial); | ||
267 | #if ADB_HOST | ||
268 | atransport* find_emulator_transport_by_adb_port(int adb_port); | ||
269 | #endif | ||
270 | |||
271 | int service_to_fd(const char *name); | ||
272 | #if ADB_HOST | ||
273 | asocket *host_service_to_socket(const char* name, const char *serial); | ||
274 | #endif | ||
275 | |||
276 | #if !ADB_HOST | ||
277 | typedef enum { | ||
278 | BACKUP, | ||
279 | RESTORE | ||
280 | } BackupOperation; | ||
281 | int backup_service(BackupOperation operation, char* args); | ||
282 | void framebuffer_service(int fd, void *cookie); | ||
283 | void log_service(int fd, void *cookie); | ||
284 | void remount_service(int fd, void *cookie); | ||
285 | char * get_log_file_path(const char * log_name); | ||
286 | #endif | ||
287 | |||
288 | /* packet allocator */ | ||
289 | apacket *get_apacket(void); | ||
290 | void put_apacket(apacket *p); | ||
291 | |||
292 | int check_header(apacket *p); | ||
293 | int check_data(apacket *p); | ||
294 | |||
295 | /* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */ | ||
296 | |||
297 | #define ADB_TRACE 1 | ||
298 | |||
299 | /* IMPORTANT: if you change the following list, don't | ||
300 | * forget to update the corresponding 'tags' table in | ||
301 | * the adb_trace_init() function implemented in adb.c | ||
302 | */ | ||
303 | typedef enum { | ||
304 | TRACE_ADB = 0, /* 0x001 */ | ||
305 | TRACE_SOCKETS, | ||
306 | TRACE_PACKETS, | ||
307 | TRACE_TRANSPORT, | ||
308 | TRACE_RWX, /* 0x010 */ | ||
309 | TRACE_USB, | ||
310 | TRACE_SYNC, | ||
311 | TRACE_SYSDEPS, | ||
312 | TRACE_JDWP, /* 0x100 */ | ||
313 | TRACE_SERVICES, | ||
314 | } AdbTrace; | ||
315 | |||
316 | #if ADB_TRACE | ||
317 | |||
318 | extern int adb_trace_mask; | ||
319 | extern unsigned char adb_trace_output_count; | ||
320 | void adb_trace_init(void); | ||
321 | |||
322 | # define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0) | ||
323 | |||
324 | /* you must define TRACE_TAG before using this macro */ | ||
325 | # define D(...) \ | ||
326 | do { \ | ||
327 | if (ADB_TRACING) { \ | ||
328 | int save_errno = errno; \ | ||
329 | adb_mutex_lock(&D_lock); \ | ||
330 | fprintf(stderr, "%s::%s():", \ | ||
331 | __FILE__, __FUNCTION__); \ | ||
332 | errno = save_errno; \ | ||
333 | fprintf(stderr, __VA_ARGS__ ); \ | ||
334 | fflush(stderr); \ | ||
335 | adb_mutex_unlock(&D_lock); \ | ||
336 | errno = save_errno; \ | ||
337 | } \ | ||
338 | } while (0) | ||
339 | # define DR(...) \ | ||
340 | do { \ | ||
341 | if (ADB_TRACING) { \ | ||
342 | int save_errno = errno; \ | ||
343 | adb_mutex_lock(&D_lock); \ | ||
344 | errno = save_errno; \ | ||
345 | fprintf(stderr, __VA_ARGS__ ); \ | ||
346 | fflush(stderr); \ | ||
347 | adb_mutex_unlock(&D_lock); \ | ||
348 | errno = save_errno; \ | ||
349 | } \ | ||
350 | } while (0) | ||
351 | #else | ||
352 | # define D(...) ((void)0) | ||
353 | # define DR(...) ((void)0) | ||
354 | # define ADB_TRACING 0 | ||
355 | #endif | ||
356 | |||
357 | |||
358 | #if !TRACE_PACKETS | ||
359 | #define print_packet(tag,p) do {} while (0) | ||
360 | #endif | ||
361 | |||
362 | #if ADB_HOST_ON_TARGET | ||
363 | /* adb and adbd are coexisting on the target, so use 5038 for adb | ||
364 | * to avoid conflicting with adbd's usage of 5037 | ||
365 | */ | ||
366 | # define DEFAULT_ADB_PORT 5038 | ||
367 | #else | ||
368 | # define DEFAULT_ADB_PORT 5037 | ||
369 | #endif | ||
370 | |||
371 | #define DEFAULT_ADB_LOCAL_TRANSPORT_PORT 5555 | ||
372 | |||
373 | #define ADB_CLASS 0xff | ||
374 | #define ADB_SUBCLASS 0x42 | ||
375 | #define ADB_PROTOCOL 0x1 | ||
376 | |||
377 | |||
378 | void local_init(int port); | ||
379 | int local_connect(int port); | ||
380 | int local_connect_arbitrary_ports(int console_port, int adb_port); | ||
381 | |||
382 | /* usb host/client interface */ | ||
383 | void usb_init(); | ||
384 | void usb_cleanup(); | ||
385 | int usb_write(usb_handle *h, const void *data, int len); | ||
386 | int usb_read(usb_handle *h, void *data, int len); | ||
387 | int usb_close(usb_handle *h); | ||
388 | void usb_kick(usb_handle *h); | ||
389 | |||
390 | /* used for USB device detection */ | ||
391 | #if ADB_HOST | ||
392 | int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol); | ||
393 | #endif | ||
394 | |||
395 | unsigned host_to_le32(unsigned n); | ||
396 | int adb_commandline(int argc, char **argv); | ||
397 | |||
398 | int connection_state(atransport *t); | ||
399 | |||
400 | #define CS_ANY -1 | ||
401 | #define CS_OFFLINE 0 | ||
402 | #define CS_BOOTLOADER 1 | ||
403 | #define CS_DEVICE 2 | ||
404 | #define CS_HOST 3 | ||
405 | #define CS_RECOVERY 4 | ||
406 | #define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */ | ||
407 | #define CS_SIDELOAD 6 | ||
408 | #define CS_UNAUTHORIZED 7 | ||
409 | |||
410 | extern int HOST; | ||
411 | extern int SHELL_EXIT_NOTIFY_FD; | ||
412 | |||
413 | #define CHUNK_SIZE (64*1024) | ||
414 | |||
415 | #if !ADB_HOST | ||
416 | #define USB_ADB_PATH "/dev/android_adb" | ||
417 | |||
418 | #define USB_FFS_ADB_PATH "/dev/usb-ffs/adb/" | ||
419 | #define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH#x | ||
420 | |||
421 | #define USB_FFS_ADB_EP0 USB_FFS_ADB_EP(ep0) | ||
422 | #define USB_FFS_ADB_OUT USB_FFS_ADB_EP(ep1) | ||
423 | #define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2) | ||
424 | #endif | ||
425 | |||
426 | int sendfailmsg(int fd, const char *reason); | ||
427 | int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s); | ||
428 | |||
429 | #ifdef __cplusplus | ||
430 | } | ||
431 | #endif | ||
432 | |||
433 | #endif | ||
diff --git a/minadbd/adb_main.c b/minadbd/adb_main.c index 66d27026..a62881d8 100644 --- a/minadbd/adb_main.c +++ b/minadbd/adb_main.c | |||
@@ -24,10 +24,12 @@ | |||
24 | #include "adb.h" | 24 | #include "adb.h" |
25 | #include "sysdeps.h" | 25 | #include "sysdeps.h" |
26 | 26 | ||
27 | int adb_main() | 27 | int adb_main(int is_daemon, int server_port) |
28 | { | 28 | { |
29 | atexit(usb_cleanup); | 29 | atexit(usb_cleanup); |
30 | 30 | ||
31 | adb_device_banner = "sideload"; | ||
32 | |||
31 | // No SIGCHLD. Let the service subproc handle its children. | 33 | // No SIGCHLD. Let the service subproc handle its children. |
32 | signal(SIGPIPE, SIG_IGN); | 34 | signal(SIGPIPE, SIG_IGN); |
33 | 35 | ||
diff --git a/minadbd/sockets.c b/minadbd/sockets.c deleted file mode 100644 index 817410d1..00000000 --- a/minadbd/sockets.c +++ /dev/null | |||
@@ -1,731 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <stdio.h> | ||
18 | #include <stdlib.h> | ||
19 | #include <unistd.h> | ||
20 | #include <errno.h> | ||
21 | #include <string.h> | ||
22 | #include <ctype.h> | ||
23 | |||
24 | #include "sysdeps.h" | ||
25 | |||
26 | #define TRACE_TAG TRACE_SOCKETS | ||
27 | #include "adb.h" | ||
28 | |||
29 | ADB_MUTEX_DEFINE( socket_list_lock ); | ||
30 | |||
31 | static void local_socket_close_locked(asocket *s); | ||
32 | |||
33 | int sendfailmsg(int fd, const char *reason) | ||
34 | { | ||
35 | char buf[9]; | ||
36 | int len; | ||
37 | len = strlen(reason); | ||
38 | if(len > 0xffff) len = 0xffff; | ||
39 | snprintf(buf, sizeof buf, "FAIL%04x", len); | ||
40 | if(writex(fd, buf, 8)) return -1; | ||
41 | return writex(fd, reason, len); | ||
42 | } | ||
43 | |||
44 | //extern int online; | ||
45 | |||
46 | static unsigned local_socket_next_id = 1; | ||
47 | |||
48 | static asocket local_socket_list = { | ||
49 | .next = &local_socket_list, | ||
50 | .prev = &local_socket_list, | ||
51 | }; | ||
52 | |||
53 | /* the the list of currently closing local sockets. | ||
54 | ** these have no peer anymore, but still packets to | ||
55 | ** write to their fd. | ||
56 | */ | ||
57 | static asocket local_socket_closing_list = { | ||
58 | .next = &local_socket_closing_list, | ||
59 | .prev = &local_socket_closing_list, | ||
60 | }; | ||
61 | |||
62 | asocket *find_local_socket(unsigned id) | ||
63 | { | ||
64 | asocket *s; | ||
65 | asocket *result = NULL; | ||
66 | |||
67 | adb_mutex_lock(&socket_list_lock); | ||
68 | for (s = local_socket_list.next; s != &local_socket_list; s = s->next) { | ||
69 | if (s->id == id) { | ||
70 | result = s; | ||
71 | break; | ||
72 | } | ||
73 | } | ||
74 | adb_mutex_unlock(&socket_list_lock); | ||
75 | |||
76 | return result; | ||
77 | } | ||
78 | |||
79 | static void | ||
80 | insert_local_socket(asocket* s, asocket* list) | ||
81 | { | ||
82 | s->next = list; | ||
83 | s->prev = s->next->prev; | ||
84 | s->prev->next = s; | ||
85 | s->next->prev = s; | ||
86 | } | ||
87 | |||
88 | |||
89 | void install_local_socket(asocket *s) | ||
90 | { | ||
91 | adb_mutex_lock(&socket_list_lock); | ||
92 | |||
93 | s->id = local_socket_next_id++; | ||
94 | insert_local_socket(s, &local_socket_list); | ||
95 | |||
96 | adb_mutex_unlock(&socket_list_lock); | ||
97 | } | ||
98 | |||
99 | void remove_socket(asocket *s) | ||
100 | { | ||
101 | // socket_list_lock should already be held | ||
102 | if (s->prev && s->next) | ||
103 | { | ||
104 | s->prev->next = s->next; | ||
105 | s->next->prev = s->prev; | ||
106 | s->next = 0; | ||
107 | s->prev = 0; | ||
108 | s->id = 0; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | void close_all_sockets(atransport *t) | ||
113 | { | ||
114 | asocket *s; | ||
115 | |||
116 | /* this is a little gross, but since s->close() *will* modify | ||
117 | ** the list out from under you, your options are limited. | ||
118 | */ | ||
119 | adb_mutex_lock(&socket_list_lock); | ||
120 | restart: | ||
121 | for(s = local_socket_list.next; s != &local_socket_list; s = s->next){ | ||
122 | if(s->transport == t || (s->peer && s->peer->transport == t)) { | ||
123 | local_socket_close_locked(s); | ||
124 | goto restart; | ||
125 | } | ||
126 | } | ||
127 | adb_mutex_unlock(&socket_list_lock); | ||
128 | } | ||
129 | |||
130 | static int local_socket_enqueue(asocket *s, apacket *p) | ||
131 | { | ||
132 | D("LS(%d): enqueue %d\n", s->id, p->len); | ||
133 | |||
134 | p->ptr = p->data; | ||
135 | |||
136 | /* if there is already data queue'd, we will receive | ||
137 | ** events when it's time to write. just add this to | ||
138 | ** the tail | ||
139 | */ | ||
140 | if(s->pkt_first) { | ||
141 | goto enqueue; | ||
142 | } | ||
143 | |||
144 | /* write as much as we can, until we | ||
145 | ** would block or there is an error/eof | ||
146 | */ | ||
147 | while(p->len > 0) { | ||
148 | int r = adb_write(s->fd, p->ptr, p->len); | ||
149 | if(r > 0) { | ||
150 | p->len -= r; | ||
151 | p->ptr += r; | ||
152 | continue; | ||
153 | } | ||
154 | if((r == 0) || (errno != EAGAIN)) { | ||
155 | D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) ); | ||
156 | s->close(s); | ||
157 | return 1; /* not ready (error) */ | ||
158 | } else { | ||
159 | break; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | if(p->len == 0) { | ||
164 | put_apacket(p); | ||
165 | return 0; /* ready for more data */ | ||
166 | } | ||
167 | |||
168 | enqueue: | ||
169 | p->next = 0; | ||
170 | if(s->pkt_first) { | ||
171 | s->pkt_last->next = p; | ||
172 | } else { | ||
173 | s->pkt_first = p; | ||
174 | } | ||
175 | s->pkt_last = p; | ||
176 | |||
177 | /* make sure we are notified when we can drain the queue */ | ||
178 | fdevent_add(&s->fde, FDE_WRITE); | ||
179 | |||
180 | return 1; /* not ready (backlog) */ | ||
181 | } | ||
182 | |||
183 | static void local_socket_ready(asocket *s) | ||
184 | { | ||
185 | /* far side is ready for data, pay attention to | ||
186 | readable events */ | ||
187 | fdevent_add(&s->fde, FDE_READ); | ||
188 | // D("LS(%d): ready()\n", s->id); | ||
189 | } | ||
190 | |||
191 | static void local_socket_close(asocket *s) | ||
192 | { | ||
193 | adb_mutex_lock(&socket_list_lock); | ||
194 | local_socket_close_locked(s); | ||
195 | adb_mutex_unlock(&socket_list_lock); | ||
196 | } | ||
197 | |||
198 | // be sure to hold the socket list lock when calling this | ||
199 | static void local_socket_destroy(asocket *s) | ||
200 | { | ||
201 | apacket *p, *n; | ||
202 | D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd); | ||
203 | |||
204 | /* IMPORTANT: the remove closes the fd | ||
205 | ** that belongs to this socket | ||
206 | */ | ||
207 | fdevent_remove(&s->fde); | ||
208 | |||
209 | /* dispose of any unwritten data */ | ||
210 | for(p = s->pkt_first; p; p = n) { | ||
211 | D("LS(%d): discarding %d bytes\n", s->id, p->len); | ||
212 | n = p->next; | ||
213 | put_apacket(p); | ||
214 | } | ||
215 | remove_socket(s); | ||
216 | free(s); | ||
217 | } | ||
218 | |||
219 | |||
220 | static void local_socket_close_locked(asocket *s) | ||
221 | { | ||
222 | D("entered. LS(%d) fd=%d\n", s->id, s->fd); | ||
223 | if(s->peer) { | ||
224 | D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n", | ||
225 | s->id, s->peer->id, s->peer->fd); | ||
226 | s->peer->peer = 0; | ||
227 | // tweak to avoid deadlock | ||
228 | if (s->peer->close == local_socket_close) { | ||
229 | local_socket_close_locked(s->peer); | ||
230 | } else { | ||
231 | s->peer->close(s->peer); | ||
232 | } | ||
233 | s->peer = 0; | ||
234 | } | ||
235 | |||
236 | /* If we are already closing, or if there are no | ||
237 | ** pending packets, destroy immediately | ||
238 | */ | ||
239 | if (s->closing || s->pkt_first == NULL) { | ||
240 | int id = s->id; | ||
241 | local_socket_destroy(s); | ||
242 | D("LS(%d): closed\n", id); | ||
243 | return; | ||
244 | } | ||
245 | |||
246 | /* otherwise, put on the closing list | ||
247 | */ | ||
248 | D("LS(%d): closing\n", s->id); | ||
249 | s->closing = 1; | ||
250 | fdevent_del(&s->fde, FDE_READ); | ||
251 | remove_socket(s); | ||
252 | D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd); | ||
253 | insert_local_socket(s, &local_socket_closing_list); | ||
254 | } | ||
255 | |||
256 | static void local_socket_event_func(int fd, unsigned ev, void *_s) | ||
257 | { | ||
258 | asocket *s = _s; | ||
259 | |||
260 | D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev); | ||
261 | |||
262 | /* put the FDE_WRITE processing before the FDE_READ | ||
263 | ** in order to simplify the code. | ||
264 | */ | ||
265 | if(ev & FDE_WRITE){ | ||
266 | apacket *p; | ||
267 | |||
268 | while((p = s->pkt_first) != 0) { | ||
269 | while(p->len > 0) { | ||
270 | int r = adb_write(fd, p->ptr, p->len); | ||
271 | if(r > 0) { | ||
272 | p->ptr += r; | ||
273 | p->len -= r; | ||
274 | continue; | ||
275 | } | ||
276 | if(r < 0) { | ||
277 | /* returning here is ok because FDE_READ will | ||
278 | ** be processed in the next iteration loop | ||
279 | */ | ||
280 | if(errno == EAGAIN) return; | ||
281 | if(errno == EINTR) continue; | ||
282 | } | ||
283 | D(" closing after write because r=%d and errno is %d\n", r, errno); | ||
284 | s->close(s); | ||
285 | return; | ||
286 | } | ||
287 | |||
288 | if(p->len == 0) { | ||
289 | s->pkt_first = p->next; | ||
290 | if(s->pkt_first == 0) s->pkt_last = 0; | ||
291 | put_apacket(p); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | /* if we sent the last packet of a closing socket, | ||
296 | ** we can now destroy it. | ||
297 | */ | ||
298 | if (s->closing) { | ||
299 | D(" closing because 'closing' is set after write\n"); | ||
300 | s->close(s); | ||
301 | return; | ||
302 | } | ||
303 | |||
304 | /* no more packets queued, so we can ignore | ||
305 | ** writable events again and tell our peer | ||
306 | ** to resume writing | ||
307 | */ | ||
308 | fdevent_del(&s->fde, FDE_WRITE); | ||
309 | s->peer->ready(s->peer); | ||
310 | } | ||
311 | |||
312 | |||
313 | if(ev & FDE_READ){ | ||
314 | apacket *p = get_apacket(); | ||
315 | unsigned char *x = p->data; | ||
316 | size_t avail = MAX_PAYLOAD; | ||
317 | int r; | ||
318 | int is_eof = 0; | ||
319 | |||
320 | while(avail > 0) { | ||
321 | r = adb_read(fd, x, avail); | ||
322 | D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n", | ||
323 | s->id, s->fd, r, r<0?errno:0, avail); | ||
324 | if(r > 0) { | ||
325 | avail -= r; | ||
326 | x += r; | ||
327 | continue; | ||
328 | } | ||
329 | if(r < 0) { | ||
330 | if(errno == EAGAIN) break; | ||
331 | if(errno == EINTR) continue; | ||
332 | } | ||
333 | |||
334 | /* r = 0 or unhandled error */ | ||
335 | is_eof = 1; | ||
336 | break; | ||
337 | } | ||
338 | D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n", | ||
339 | s->id, s->fd, r, is_eof, s->fde.force_eof); | ||
340 | if((avail == MAX_PAYLOAD) || (s->peer == 0)) { | ||
341 | put_apacket(p); | ||
342 | } else { | ||
343 | p->len = MAX_PAYLOAD - avail; | ||
344 | |||
345 | r = s->peer->enqueue(s->peer, p); | ||
346 | D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r); | ||
347 | |||
348 | if(r < 0) { | ||
349 | /* error return means they closed us as a side-effect | ||
350 | ** and we must return immediately. | ||
351 | ** | ||
352 | ** note that if we still have buffered packets, the | ||
353 | ** socket will be placed on the closing socket list. | ||
354 | ** this handler function will be called again | ||
355 | ** to process FDE_WRITE events. | ||
356 | */ | ||
357 | return; | ||
358 | } | ||
359 | |||
360 | if(r > 0) { | ||
361 | /* if the remote cannot accept further events, | ||
362 | ** we disable notification of READs. They'll | ||
363 | ** be enabled again when we get a call to ready() | ||
364 | */ | ||
365 | fdevent_del(&s->fde, FDE_READ); | ||
366 | } | ||
367 | } | ||
368 | /* Don't allow a forced eof if data is still there */ | ||
369 | if((s->fde.force_eof && !r) || is_eof) { | ||
370 | D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof); | ||
371 | s->close(s); | ||
372 | } | ||
373 | } | ||
374 | |||
375 | if(ev & FDE_ERROR){ | ||
376 | /* this should be caught be the next read or write | ||
377 | ** catching it here means we may skip the last few | ||
378 | ** bytes of readable data. | ||
379 | */ | ||
380 | // s->close(s); | ||
381 | D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd); | ||
382 | |||
383 | return; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | asocket *create_local_socket(int fd) | ||
388 | { | ||
389 | asocket *s = calloc(1, sizeof(asocket)); | ||
390 | if (s == NULL) fatal("cannot allocate socket"); | ||
391 | s->fd = fd; | ||
392 | s->enqueue = local_socket_enqueue; | ||
393 | s->ready = local_socket_ready; | ||
394 | s->close = local_socket_close; | ||
395 | install_local_socket(s); | ||
396 | |||
397 | fdevent_install(&s->fde, fd, local_socket_event_func, s); | ||
398 | /* fdevent_add(&s->fde, FDE_ERROR); */ | ||
399 | //fprintf(stderr, "Created local socket in create_local_socket \n"); | ||
400 | D("LS(%d): created (fd=%d)\n", s->id, s->fd); | ||
401 | return s; | ||
402 | } | ||
403 | |||
404 | asocket *create_local_service_socket(const char *name) | ||
405 | { | ||
406 | asocket *s; | ||
407 | int fd; | ||
408 | |||
409 | fd = service_to_fd(name); | ||
410 | if(fd < 0) return 0; | ||
411 | |||
412 | s = create_local_socket(fd); | ||
413 | D("LS(%d): bound to '%s' via %d\n", s->id, name, fd); | ||
414 | return s; | ||
415 | } | ||
416 | |||
417 | /* a Remote socket is used to send/receive data to/from a given transport object | ||
418 | ** it needs to be closed when the transport is forcibly destroyed by the user | ||
419 | */ | ||
420 | typedef struct aremotesocket { | ||
421 | asocket socket; | ||
422 | adisconnect disconnect; | ||
423 | } aremotesocket; | ||
424 | |||
425 | static int remote_socket_enqueue(asocket *s, apacket *p) | ||
426 | { | ||
427 | D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n", | ||
428 | s->id, s->fd, s->peer->fd); | ||
429 | p->msg.command = A_WRTE; | ||
430 | p->msg.arg0 = s->peer->id; | ||
431 | p->msg.arg1 = s->id; | ||
432 | p->msg.data_length = p->len; | ||
433 | send_packet(p, s->transport); | ||
434 | return 1; | ||
435 | } | ||
436 | |||
437 | static void remote_socket_ready(asocket *s) | ||
438 | { | ||
439 | D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n", | ||
440 | s->id, s->fd, s->peer->fd); | ||
441 | apacket *p = get_apacket(); | ||
442 | p->msg.command = A_OKAY; | ||
443 | p->msg.arg0 = s->peer->id; | ||
444 | p->msg.arg1 = s->id; | ||
445 | send_packet(p, s->transport); | ||
446 | } | ||
447 | |||
448 | static void remote_socket_close(asocket *s) | ||
449 | { | ||
450 | D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n", | ||
451 | s->id, s->fd, s->peer?s->peer->fd:-1); | ||
452 | apacket *p = get_apacket(); | ||
453 | p->msg.command = A_CLSE; | ||
454 | if(s->peer) { | ||
455 | p->msg.arg0 = s->peer->id; | ||
456 | s->peer->peer = 0; | ||
457 | D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n", | ||
458 | s->id, s->peer->id, s->peer->fd); | ||
459 | s->peer->close(s->peer); | ||
460 | } | ||
461 | p->msg.arg1 = s->id; | ||
462 | send_packet(p, s->transport); | ||
463 | D("RS(%d): closed\n", s->id); | ||
464 | remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect ); | ||
465 | free(s); | ||
466 | } | ||
467 | |||
468 | static void remote_socket_disconnect(void* _s, atransport* t) | ||
469 | { | ||
470 | asocket* s = _s; | ||
471 | asocket* peer = s->peer; | ||
472 | |||
473 | D("remote_socket_disconnect RS(%d)\n", s->id); | ||
474 | if (peer) { | ||
475 | peer->peer = NULL; | ||
476 | peer->close(peer); | ||
477 | } | ||
478 | remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect ); | ||
479 | free(s); | ||
480 | } | ||
481 | |||
482 | asocket *create_remote_socket(unsigned id, atransport *t) | ||
483 | { | ||
484 | asocket *s = calloc(1, sizeof(aremotesocket)); | ||
485 | adisconnect* dis = &((aremotesocket*)s)->disconnect; | ||
486 | |||
487 | if (s == NULL) fatal("cannot allocate socket"); | ||
488 | s->id = id; | ||
489 | s->enqueue = remote_socket_enqueue; | ||
490 | s->ready = remote_socket_ready; | ||
491 | s->close = remote_socket_close; | ||
492 | s->transport = t; | ||
493 | |||
494 | dis->func = remote_socket_disconnect; | ||
495 | dis->opaque = s; | ||
496 | add_transport_disconnect( t, dis ); | ||
497 | D("RS(%d): created\n", s->id); | ||
498 | return s; | ||
499 | } | ||
500 | |||
501 | void connect_to_remote(asocket *s, const char *destination) | ||
502 | { | ||
503 | D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd); | ||
504 | apacket *p = get_apacket(); | ||
505 | int len = strlen(destination) + 1; | ||
506 | |||
507 | if(len > (MAX_PAYLOAD-1)) { | ||
508 | fatal("destination oversized"); | ||
509 | } | ||
510 | |||
511 | D("LS(%d): connect('%s')\n", s->id, destination); | ||
512 | p->msg.command = A_OPEN; | ||
513 | p->msg.arg0 = s->id; | ||
514 | p->msg.data_length = len; | ||
515 | strcpy((char*) p->data, destination); | ||
516 | send_packet(p, s->transport); | ||
517 | } | ||
518 | |||
519 | |||
520 | /* this is used by magic sockets to rig local sockets to | ||
521 | send the go-ahead message when they connect */ | ||
522 | static void local_socket_ready_notify(asocket *s) | ||
523 | { | ||
524 | s->ready = local_socket_ready; | ||
525 | s->close = local_socket_close; | ||
526 | adb_write(s->fd, "OKAY", 4); | ||
527 | s->ready(s); | ||
528 | } | ||
529 | |||
530 | /* this is used by magic sockets to rig local sockets to | ||
531 | send the failure message if they are closed before | ||
532 | connected (to avoid closing them without a status message) */ | ||
533 | static void local_socket_close_notify(asocket *s) | ||
534 | { | ||
535 | s->ready = local_socket_ready; | ||
536 | s->close = local_socket_close; | ||
537 | sendfailmsg(s->fd, "closed"); | ||
538 | s->close(s); | ||
539 | } | ||
540 | |||
541 | unsigned unhex(unsigned char *s, int len) | ||
542 | { | ||
543 | unsigned n = 0, c; | ||
544 | |||
545 | while(len-- > 0) { | ||
546 | switch((c = *s++)) { | ||
547 | case '0': case '1': case '2': | ||
548 | case '3': case '4': case '5': | ||
549 | case '6': case '7': case '8': | ||
550 | case '9': | ||
551 | c -= '0'; | ||
552 | break; | ||
553 | case 'a': case 'b': case 'c': | ||
554 | case 'd': case 'e': case 'f': | ||
555 | c = c - 'a' + 10; | ||
556 | break; | ||
557 | case 'A': case 'B': case 'C': | ||
558 | case 'D': case 'E': case 'F': | ||
559 | c = c - 'A' + 10; | ||
560 | break; | ||
561 | default: | ||
562 | return 0xffffffff; | ||
563 | } | ||
564 | |||
565 | n = (n << 4) | c; | ||
566 | } | ||
567 | |||
568 | return n; | ||
569 | } | ||
570 | |||
571 | /* skip_host_serial return the position in a string | ||
572 | skipping over the 'serial' parameter in the ADB protocol, | ||
573 | where parameter string may be a host:port string containing | ||
574 | the protocol delimiter (colon). */ | ||
575 | char *skip_host_serial(char *service) { | ||
576 | char *first_colon, *serial_end; | ||
577 | |||
578 | first_colon = strchr(service, ':'); | ||
579 | if (!first_colon) { | ||
580 | /* No colon in service string. */ | ||
581 | return NULL; | ||
582 | } | ||
583 | serial_end = first_colon; | ||
584 | if (isdigit(serial_end[1])) { | ||
585 | serial_end++; | ||
586 | while ((*serial_end) && isdigit(*serial_end)) { | ||
587 | serial_end++; | ||
588 | } | ||
589 | if ((*serial_end) != ':') { | ||
590 | // Something other than numbers was found, reset the end. | ||
591 | serial_end = first_colon; | ||
592 | } | ||
593 | } | ||
594 | return serial_end; | ||
595 | } | ||
596 | |||
597 | static int smart_socket_enqueue(asocket *s, apacket *p) | ||
598 | { | ||
599 | unsigned len; | ||
600 | |||
601 | D("SS(%d): enqueue %d\n", s->id, p->len); | ||
602 | |||
603 | if(s->pkt_first == 0) { | ||
604 | s->pkt_first = p; | ||
605 | s->pkt_last = p; | ||
606 | } else { | ||
607 | if((s->pkt_first->len + p->len) > MAX_PAYLOAD) { | ||
608 | D("SS(%d): overflow\n", s->id); | ||
609 | put_apacket(p); | ||
610 | goto fail; | ||
611 | } | ||
612 | |||
613 | memcpy(s->pkt_first->data + s->pkt_first->len, | ||
614 | p->data, p->len); | ||
615 | s->pkt_first->len += p->len; | ||
616 | put_apacket(p); | ||
617 | |||
618 | p = s->pkt_first; | ||
619 | } | ||
620 | |||
621 | /* don't bother if we can't decode the length */ | ||
622 | if(p->len < 4) return 0; | ||
623 | |||
624 | len = unhex(p->data, 4); | ||
625 | if((len < 1) || (len > 1024)) { | ||
626 | D("SS(%d): bad size (%d)\n", s->id, len); | ||
627 | goto fail; | ||
628 | } | ||
629 | |||
630 | D("SS(%d): len is %d\n", s->id, len ); | ||
631 | /* can't do anything until we have the full header */ | ||
632 | if((len + 4) > p->len) { | ||
633 | D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len); | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | p->data[len + 4] = 0; | ||
638 | |||
639 | D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4)); | ||
640 | |||
641 | if (s->transport == NULL) { | ||
642 | char* error_string = "unknown failure"; | ||
643 | s->transport = acquire_one_transport (CS_ANY, | ||
644 | kTransportAny, NULL, &error_string); | ||
645 | |||
646 | if (s->transport == NULL) { | ||
647 | sendfailmsg(s->peer->fd, error_string); | ||
648 | goto fail; | ||
649 | } | ||
650 | } | ||
651 | |||
652 | if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) { | ||
653 | /* if there's no remote we fail the connection | ||
654 | ** right here and terminate it | ||
655 | */ | ||
656 | sendfailmsg(s->peer->fd, "device offline (x)"); | ||
657 | goto fail; | ||
658 | } | ||
659 | |||
660 | |||
661 | /* instrument our peer to pass the success or fail | ||
662 | ** message back once it connects or closes, then | ||
663 | ** detach from it, request the connection, and | ||
664 | ** tear down | ||
665 | */ | ||
666 | s->peer->ready = local_socket_ready_notify; | ||
667 | s->peer->close = local_socket_close_notify; | ||
668 | s->peer->peer = 0; | ||
669 | /* give him our transport and upref it */ | ||
670 | s->peer->transport = s->transport; | ||
671 | |||
672 | connect_to_remote(s->peer, (char*) (p->data + 4)); | ||
673 | s->peer = 0; | ||
674 | s->close(s); | ||
675 | return 1; | ||
676 | |||
677 | fail: | ||
678 | /* we're going to close our peer as a side-effect, so | ||
679 | ** return -1 to signal that state to the local socket | ||
680 | ** who is enqueueing against us | ||
681 | */ | ||
682 | s->close(s); | ||
683 | return -1; | ||
684 | } | ||
685 | |||
686 | static void smart_socket_ready(asocket *s) | ||
687 | { | ||
688 | D("SS(%d): ready\n", s->id); | ||
689 | } | ||
690 | |||
691 | static void smart_socket_close(asocket *s) | ||
692 | { | ||
693 | D("SS(%d): closed\n", s->id); | ||
694 | if(s->pkt_first){ | ||
695 | put_apacket(s->pkt_first); | ||
696 | } | ||
697 | if(s->peer) { | ||
698 | s->peer->peer = 0; | ||
699 | s->peer->close(s->peer); | ||
700 | s->peer = 0; | ||
701 | } | ||
702 | free(s); | ||
703 | } | ||
704 | |||
705 | asocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act)) | ||
706 | { | ||
707 | D("Creating smart socket \n"); | ||
708 | asocket *s = calloc(1, sizeof(asocket)); | ||
709 | if (s == NULL) fatal("cannot allocate socket"); | ||
710 | s->enqueue = smart_socket_enqueue; | ||
711 | s->ready = smart_socket_ready; | ||
712 | s->close = smart_socket_close; | ||
713 | s->extra = action_cb; | ||
714 | |||
715 | D("SS(%d): created %p\n", s->id, action_cb); | ||
716 | return s; | ||
717 | } | ||
718 | |||
719 | void smart_socket_action(asocket *s, const char *act) | ||
720 | { | ||
721 | |||
722 | } | ||
723 | |||
724 | void connect_to_smartsocket(asocket *s) | ||
725 | { | ||
726 | D("Connecting to smart socket \n"); | ||
727 | asocket *ss = create_smart_socket(smart_socket_action); | ||
728 | s->peer = ss; | ||
729 | ss->peer = s; | ||
730 | s->ready(s); | ||
731 | } | ||