aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Albert2015-02-19 15:21:14 -0600
committerDan Albert2015-02-19 17:41:35 -0600
commitf3a5726919ce35d3f5e628e9561496470195ac1f (patch)
tree247e812a898020502652e1cae9f244acab0aa517 /minadbd
parent4eb6c71e7f013e684828ae6216f61b83be552282 (diff)
downloadplatform-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.mk3
-rw-r--r--minadbd/README.txt37
-rw-r--r--minadbd/adb.c372
-rw-r--r--minadbd/adb.h433
-rw-r--r--minadbd/adb_main.c4
-rw-r--r--minadbd/sockets.c731
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)
11include $(CLEAR_VARS) 11include $(CLEAR_VARS)
12 12
13LOCAL_SRC_FILES := \ 13LOCAL_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
20LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter 18LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
21LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE 19LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
22LOCAL_C_INCLUDES := bootable/recovery system/core/adb 20LOCAL_C_INCLUDES := bootable/recovery system/core/adb
21LOCAL_WHOLE_STATIC_LIBRARIES := libadbd
23 22
24LOCAL_MODULE := libminadbd 23LOCAL_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 @@
1The contents of this directory are copied from system/core/adb, with 1minadbd is now mostly built from libadbd. The fuse features are unique to
2the following changes: 2minadbd, and services.c has been modified as follows:
3 3
4adb.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
14adb.h
15 - minor changes to match adb.c changes
16
17sockets.c
18 - references to JDWP removed
19 - ADB_HOST code removed
20
21services.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
28Android.mk
29 - only builds in adbd mode; builds as static library instead of a
30 standalone executable.
31
32sysdeps.h
33 - changes adb_creat() to use O_NOFOLLOW
34
35transport.c
36 - removed ADB_HOST code
37
38transport_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
34ADB_MUTEX_DEFINE( D_lock );
35#endif
36
37int HOST = 0;
38
39static const char *adb_device_banner = "sideload";
40
41void 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
52void 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
63int 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 */
70void 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
129apacket *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
137void put_apacket(apacket *p)
138{
139 free(p);
140}
141
142void handle_online(void)
143{
144 D("adb: online\n");
145}
146
147void 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
156void 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
194static 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
204static 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
214static 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
227void 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
283void 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
26extern "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
45typedef struct amessage amessage;
46typedef struct apacket apacket;
47typedef struct asocket asocket;
48typedef struct aservice aservice;
49typedef struct atransport atransport;
50typedef struct adisconnect adisconnect;
51typedef struct usb_handle usb_handle;
52
53struct 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
62struct 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*/
77struct 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*/
142struct 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*/
160typedef enum transport_type {
161 kTransportUsb,
162 kTransportLocal,
163 kTransportAny,
164 kTransportHost,
165} transport_type;
166
167struct 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
200void print_packet(const char *label, apacket *p);
201
202asocket *find_local_socket(unsigned id);
203void install_local_socket(asocket *s);
204void remove_socket(asocket *s);
205void close_all_sockets(atransport *t);
206
207#define LOCAL_CLIENT_PREFIX "emulator-"
208
209asocket *create_local_socket(int fd);
210asocket *create_local_service_socket(const char *destination);
211
212asocket *create_remote_socket(unsigned id, atransport *t);
213void connect_to_remote(asocket *s, const char *destination);
214void connect_to_smartsocket(asocket *s);
215
216void fatal(const char *fmt, ...);
217void fatal_errno(const char *fmt, ...);
218
219void handle_packet(apacket *p, atransport *t);
220void send_packet(apacket *p, atransport *t);
221
222void get_my_path(char *s, size_t maxLen);
223int launch_server(int server_port);
224int adb_main();
225
226
227/* transports are ref-counted
228** get_device_transport does an acquire on your behalf before returning
229*/
230void init_transport_registration(void);
231int list_transports(char *buf, size_t bufsize);
232void update_transports(void);
233
234asocket* 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*/
241atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char **error_out);
242void add_transport_disconnect( atransport* t, adisconnect* dis );
243void remove_transport_disconnect( atransport* t, adisconnect* dis );
244void run_transport_disconnects( atransport* t );
245void kick_transport( atransport* t );
246
247/* initialize a transport object's func pointers and state */
248#if ADB_HOST
249int get_available_local_transport_index();
250#endif
251void init_usb_transport(atransport *t, usb_handle *usb, int state);
252
253/* for MacOS X cleanup */
254void close_usb_devices();
255
256/* these should only be used for the "adb disconnect" command */
257void unregister_transport(atransport *t);
258void unregister_all_tcp_transports();
259
260void 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 */
264void unregister_usb_transport(usb_handle *usb);
265
266atransport *find_transport(const char *serial);
267#if ADB_HOST
268atransport* find_emulator_transport_by_adb_port(int adb_port);
269#endif
270
271int service_to_fd(const char *name);
272#if ADB_HOST
273asocket *host_service_to_socket(const char* name, const char *serial);
274#endif
275
276#if !ADB_HOST
277typedef enum {
278 BACKUP,
279 RESTORE
280} BackupOperation;
281int backup_service(BackupOperation operation, char* args);
282void framebuffer_service(int fd, void *cookie);
283void log_service(int fd, void *cookie);
284void remount_service(int fd, void *cookie);
285char * get_log_file_path(const char * log_name);
286#endif
287
288/* packet allocator */
289apacket *get_apacket(void);
290void put_apacket(apacket *p);
291
292int check_header(apacket *p);
293int 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 */
303typedef 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
378void local_init(int port);
379int local_connect(int port);
380int local_connect_arbitrary_ports(int console_port, int adb_port);
381
382/* usb host/client interface */
383void usb_init();
384void usb_cleanup();
385int usb_write(usb_handle *h, const void *data, int len);
386int usb_read(usb_handle *h, void *data, int len);
387int usb_close(usb_handle *h);
388void usb_kick(usb_handle *h);
389
390/* used for USB device detection */
391#if ADB_HOST
392int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
393#endif
394
395unsigned host_to_le32(unsigned n);
396int adb_commandline(int argc, char **argv);
397
398int 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
410extern int HOST;
411extern 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
426int sendfailmsg(int fd, const char *reason);
427int 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
27int adb_main() 27int 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
29ADB_MUTEX_DEFINE( socket_list_lock );
30
31static void local_socket_close_locked(asocket *s);
32
33int 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
46static unsigned local_socket_next_id = 1;
47
48static 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*/
57static asocket local_socket_closing_list = {
58 .next = &local_socket_closing_list,
59 .prev = &local_socket_closing_list,
60};
61
62asocket *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
79static void
80insert_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
89void 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
99void 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
112void 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);
120restart:
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
130static 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
168enqueue:
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
183static 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
191static 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
199static 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
220static 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
256static 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
387asocket *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
404asocket *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*/
420typedef struct aremotesocket {
421 asocket socket;
422 adisconnect disconnect;
423} aremotesocket;
424
425static 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
437static 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
448static 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
468static 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
482asocket *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
501void 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 */
522static 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) */
533static 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
541unsigned 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). */
575char *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
597static 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
677fail:
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
686static void smart_socket_ready(asocket *s)
687{
688 D("SS(%d): ready\n", s->id);
689}
690
691static 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
705asocket *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
719void smart_socket_action(asocket *s, const char *act)
720{
721
722}
723
724void 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}