1 /*
2 * Copyright (C) 2011 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 /*
18 * Encapsulates exchange protocol between the emulator, and an Android device
19 * that is connected to the host via USB. The communication is established over
20 * a TCP port forwarding, enabled by ADB.
21 */
22
23 #include "android/android-device.h"
24 #include "utils/panic.h"
25 #include "iolooper.h"
26
27 #define E(...) derror(__VA_ARGS__)
28 #define W(...) dwarning(__VA_ARGS__)
29 #define D(...) VERBOSE_PRINT(adevice,__VA_ARGS__)
30 #define D_ACTIVE VERBOSE_CHECK(adevice)
31
32 /********************************************************************************
33 * Common android device socket
34 *******************************************************************************/
35
36 /* Milliseconds between retrying asynchronous connections to the device. */
37 #define ADS_RETRY_CONNECTION_TIMEOUT 3000
38
39 /* Socket type. */
40 typedef enum ADSType {
41 /* Query socket. */
42 ADS_TYPE_QUERY = 0,
43 /* Events socket. */
44 ADS_TYPE_EVENT = 1
45 } ADSType;
46
47 /* Status of the socket. */
48 typedef enum ADSStatus {
49 /* Socket is disconnected. */
50 ADS_DISCONNECTED,
51 /* Connection process has been started. */
52 ADS_CONNECTING,
53 /* Connection has been established. */
54 ADS_CONNECTED,
55 /* Socket has been registered with the server. */
56 ADS_REGISTERED,
57 } ADSStatus;
58
59 /* Identifies socket as a "query" socket with the server. */
60 static const char* _ads_query_socket_id = "query";
61 /* Identifies socket as an "event" socket with the server. */
62 static const char* _ads_event_socket_id = "event";
63
64 /* Android device socket descriptor. */
65 typedef struct AndroidDevSocket AndroidDevSocket;
66
67 /*
68 * Callback routines.
69 */
70
71 /* Callback routine that is called when a socket is connected.
72 * Param:
73 * opaque - Opaque pointer associated with the socket. Typicaly it's the same
74 * pointer that is associated with AndroidDevice instance.
75 * ads - Connection socket.
76 * failure - If zero, indicates that socket has been successuly connected. If a
77 * connection error has occured, this parameter contains the error code (as
78 * in 'errno).
79 */
80 typedef void (*ads_socket_connected_cb)(void* opaque,
81 struct AndroidDevSocket* ads,
82 int failure);
83
84 /* Android device socket descriptor. */
85 struct AndroidDevSocket {
86 /* Socket type. */
87 ADSType type;
88 /* Socket status. */
89 ADSStatus socket_status;
90 /* TCP address for the socket. */
91 SockAddress address;
92 /* Android device descriptor that owns the socket. */
93 AndroidDevice* ad;
94 /* Opaque pointer associated with the socket. Typicaly it's the same
95 * pointer that is associated with AndroidDevice instance.*/
96 void* opaque;
97 /* Deadline for current I/O performed on the socket. */
98 Duration deadline;
99 /* Socket's file descriptor. */
100 int fd;
101 };
102
103 /* Query socket descriptor. */
104 typedef struct AndroidQuerySocket {
105 /* Common device socket. */
106 AndroidDevSocket dev_socket;
107 } AndroidQuerySocket;
108
109 /* Describes data to send via an asynchronous socket. */
110 typedef struct AsyncSendBuffer {
111 /* Next buffer to send. */
112 struct AsyncSendBuffer* next;
113 /* Callback to invoke when data transfer is completed. */
114 async_send_cb complete_cb;
115 /* An opaque pointer to pass to the transfer completion callback. */
116 void* complete_opaque;
117 /* Data to send. */
118 uint8_t* data;
119 /* Size of the entire data buffer. */
120 int data_size;
121 /* Remaining bytes to send. */
122 int data_remaining;
123 /* Boolean flag indicating whether to free data buffer upon completion. */
124 int free_on_completion;
125 } AsyncSendBuffer;
126
127 /* Event socket descriptor. */
128 typedef struct AndroidEventSocket {
129 /* Common socket descriptor. */
130 AndroidDevSocket dev_socket;
131 /* Asynchronous connector to the device. */
132 AsyncConnector connector[1];
133 /* I/O port for asynchronous I/O on this socket. */
134 LoopIo io[1];
135 /* Asynchronous string reader. */
136 AsyncLineReader alr;
137 /* Callback to call at the end of the asynchronous connection to this socket.
138 * Can be NULL. */
139 ads_socket_connected_cb on_connected;
140 /* Callback to call when an event is received on this socket. Can be NULL. */
141 event_cb on_event;
142 /* Lists buffers that are pending to be sent. */
143 AsyncSendBuffer* send_pending;
144 } AndroidEventSocket;
145
146 /* Android device descriptor. */
147 struct AndroidDevice {
148 /* Query socket for the device. */
149 AndroidQuerySocket query_socket;
150 /* Event socket for the device. */
151 AndroidEventSocket event_socket;
152 /* An opaque pointer associated with this descriptor. */
153 void* opaque;
154 /* I/O looper for synchronous I/O on the sockets for this device. */
155 IoLooper* io_looper;
156 /* Timer that is used to retry asynchronous connections. */
157 LoopTimer timer[1];
158 /* I/O looper for asynchronous I/O. */
159 Looper* looper;
160 /* Callback to call when device is fully connected. */
161 device_connected_cb on_connected;
162 /* I/O failure callback .*/
163 io_failure_cb on_io_failure;
164 };
165
166 /* Creates descriptor for a buffer to send asynchronously.
167 * Param:
168 * data, size - Buffer to send.
169 * free_on_close - Boolean flag indicating whether to free data buffer upon
170 * completion.
171 * cb - Callback to invoke when data transfer is completed.
172 * opaque - An opaque pointer to pass to the transfer completion callback.
173 */
174 static AsyncSendBuffer*
_async_send_buffer_create(void * data,int size,int free_on_close,async_send_cb cb,void * opaque)175 _async_send_buffer_create(void* data,
176 int size,
177 int free_on_close,
178 async_send_cb cb,
179 void* opaque)
180 {
181 AsyncSendBuffer* desc = malloc(sizeof(AsyncSendBuffer));
182 if (desc == NULL) {
183 APANIC("Unable to allocate %d bytes for AsyncSendBuffer",
184 sizeof(AsyncSendBuffer));
185 }
186 desc->next = NULL;
187 desc->data = (uint8_t*)data;
188 desc->data_size = desc->data_remaining = size;
189 desc->free_on_completion = free_on_close;
190 desc->complete_cb = cb;
191 desc->complete_opaque = opaque;
192
193 return desc;
194 }
195
196 /* Completes data transfer for the given descriptor.
197 * Note that this routine will free the descriptor.
198 * Param:
199 * desc - Asynchronous data transfer descriptor. Will be freed upon the exit
200 * from this routine.
201 * res - Data transfer result.
202 */
203 static void
_async_send_buffer_complete(AsyncSendBuffer * desc,ATResult res)204 _async_send_buffer_complete(AsyncSendBuffer* desc, ATResult res)
205 {
206 /* Invoke completion callback (if present) */
207 if (desc->complete_cb) {
208 desc->complete_cb(desc->complete_opaque, res, desc->data, desc->data_size,
209 desc->data_size - desc->data_remaining);
210 }
211
212 /* Free data buffer (if required) */
213 if (desc->free_on_completion) {
214 free(desc->data);
215 }
216
217 /* Free the descriptor itself. */
218 free(desc);
219 }
220
221 /********************************************************************************
222 * Common socket declarations
223 *******************************************************************************/
224
225 /* Initializes common device socket.
226 * Param:
227 * ads - Socket descriptor to initialize.
228 * opaque - An opaque pointer to associate with the socket. Typicaly it's the
229 * same pointer that is associated with AndroidDevice instance.
230 * ad - Android device descriptor that owns the socket.
231 * port - Socket's TCP port.
232 * type - Socket type (query, or event).
233 */
234 static int _android_dev_socket_init(AndroidDevSocket* ads,
235 void* opaque,
236 AndroidDevice* ad,
237 int port,
238 ADSType type);
239
240 /* Destroys socket descriptor. */
241 static void _android_dev_socket_destroy(AndroidDevSocket* ads);
242
243 /* Callback that is ivoked from _android_dev_socket_connect when a file
244 * descriptor has been created for a socket.
245 * Param:
246 * ads - Socket descritor.
247 * opaque - An opaque pointer associated with the callback.
248 */
249 typedef void (*on_socked_fd_created)(AndroidDevSocket* ads, void* opaque);
250
251 /* Synchronously connects to the socket, and registers it with the server.
252 * Param:
253 * ads - Socket to connect. Must have 'deadline' field properly setup.
254 * cb, opaque - A callback to invoke (and opaque parameters to pass to the
255 * callback) when a file descriptor has been created for a socket. These
256 * parameters are optional and can be NULL.
257 * Return:
258 * 0 on success, -1 on failure with errno containing the reason for failure.
259 */
260 static int _android_dev_socket_connect(AndroidDevSocket* ads,
261 on_socked_fd_created cb,
262 void* opaque);
263
264 /* Synchronously registers a connected socket with the server.
265 * Param:
266 * ads - Socket to register. Must be connected, and must have 'deadline' field
267 * properly setup.
268 * Return:
269 * 0 on success, -1 on failure with errno containing the reason for failure.
270 */
271 static int _android_dev_socket_register(AndroidDevSocket* ads);
272
273 /* Disconnects the socket (if it was connected) */
274 static void _android_dev_socket_disconnect(AndroidDevSocket* ads);
275
276 /* Synchronously sends data to the socket.
277 * Param:
278 * ads - Socket to send the data to. Must be connected, and must have 'deadline'
279 * field properly setup.
280 * buff, buffsize - Buffer to send.
281 * Return:
282 * Number of bytes sent on success, or -1 on failure with errno containing the
283 * reason for failure.
284 */
285 static int _android_dev_socket_send(AndroidDevSocket* ads,
286 const char* buff,
287 int buffsize);
288
289 /* Synchronously receives data from the socket.
290 * Param:
291 * ads - Socket to receive the data from. Must be connected, and must have
292 * 'deadline' field properly setup.
293 * buff, buffsize - Buffer where to receive data.
294 * Return:
295 * Number of bytes received on success, or -1 on failure with errno containing
296 * the reason for failure.
297 */
298 static int _android_dev_socket_recv(AndroidDevSocket* ads,
299 char* buf,
300 int bufsize);
301
302 /* Synchronously reads zero-terminated string from the socket.
303 * Param:
304 * ads - Socket to read the string from. Must be connected, and must have
305 * 'deadline' field properly setup.
306 * str, strsize - Buffer where to read the string.
307 * Return:
308 * Number of charactes read into the string buffer (including zero-terminator)
309 * on success, or -1 on failure with 'errno' containing the reason for failure.
310 * If this routine returns -1, and errno contains ENOMEM, this is an indicator
311 * that supplied string buffer was too small for the receiving string.
312 */
313 static int _android_dev_socket_read_string(AndroidDevSocket* ads,
314 char* str,
315 int strsize);
316
317 /* Synchronously reads zero-terminated query response from the socket.
318 * All queries respond with an 'ok', or 'ko' prefix, indicating a success, or
319 * failure. Prefix can be followed by more query response data, separated from
320 * the prefix with a ':' character. This routine helps separating prefix from the
321 * data, by placing only the query response data into provided buffer. 'ko' or
322 * 'ok' will be encoded in the return value.
323 * Param:
324 * ads - Socket to read the response from. Must be connected, and must have
325 * 'deadline' field properly setup.
326 * data, datasize - Buffer where to read the query response data.
327 * Return:
328 * Number of charactes read into the data buffer (including zero-terminator) on
329 * success, or -1 on failure with errno containing the reason for failure.
330 * If the query has been completed with 'ko', this routine will return -1, with
331 * errno set to 0. If this routine returned -1, and errno is set to EINVAL, this
332 * indicates that reply string didn't match expected query reply format.
333 */
334 static int _android_dev_socket_read_response(AndroidDevSocket* ads,
335 char* str,
336 int strsize);
337
338 /* Gets ID string for the channel. */
339 AINLINED const char*
_ads_id_str(AndroidDevSocket * ads)340 _ads_id_str(AndroidDevSocket* ads)
341 {
342 return (ads->type == ADS_TYPE_QUERY) ? _ads_query_socket_id :
343 _ads_event_socket_id;
344 }
345
346 /* Gets socket's TCP port. */
347 AINLINED int
_ads_port(AndroidDevSocket * ads)348 _ads_port(AndroidDevSocket* ads)
349 {
350 return sock_address_get_port(&ads->address);
351 }
352
353 /* Gets synchronous I/O looper for the socket. */
354 AINLINED IoLooper*
_ads_io_looper(AndroidDevSocket * ads)355 _ads_io_looper(AndroidDevSocket* ads)
356 {
357 return ads->ad->io_looper;
358 }
359
360 /* Sets deadline on a socket operation, given relative timeout.
361 * Param:
362 * ads - Socket descriptor to set deadline for.
363 * to - Relative timeout (in millisec) for the operation.
364 * AD_INFINITE_WAIT passed in this parameter means "no deadline".
365 */
366 AINLINED void
_ads_set_deadline(AndroidDevSocket * ads,int to)367 _ads_set_deadline(AndroidDevSocket* ads, int to)
368 {
369 ads->deadline = (to == AD_INFINITE_WAIT) ? DURATION_INFINITE :
370 iolooper_now() + to;
371 }
372
373 /********************************************************************************
374 * Common socket implementation
375 *******************************************************************************/
376
377 static int
_android_dev_socket_init(AndroidDevSocket * ads,void * opaque,AndroidDevice * ad,int port,ADSType type)378 _android_dev_socket_init(AndroidDevSocket* ads,
379 void* opaque,
380 AndroidDevice* ad,
381 int port,
382 ADSType type)
383 {
384 ads->type = type;
385 ads->socket_status = ADS_DISCONNECTED;
386 ads->opaque = opaque;
387 ads->ad = ad;
388 ads->fd = -1;
389 sock_address_init_inet(&ads->address, SOCK_ADDRESS_INET_LOOPBACK, port);
390
391 return 0;
392 }
393
394 static void
_android_dev_socket_destroy(AndroidDevSocket * ads)395 _android_dev_socket_destroy(AndroidDevSocket* ads)
396 {
397 /* Make sure it's disconnected. */
398 _android_dev_socket_disconnect(ads);
399
400 /* Finalize socket address. */
401 sock_address_done(&ads->address);
402 memset(&ads->address, 0, sizeof(ads->address));
403 }
404
405 static int
_android_dev_socket_connect(AndroidDevSocket * ads,on_socked_fd_created cb,void * opaque)406 _android_dev_socket_connect(AndroidDevSocket* ads,
407 on_socked_fd_created cb,
408 void* opaque)
409 {
410 int res;
411
412 /* Create communication socket. */
413 ads->fd = socket_create_inet(SOCKET_STREAM);
414 if (ads->fd < 0) {
415 D("Unable to create socket for channel '%s'@%d: %s",
416 _ads_id_str(ads), _ads_port(ads), strerror(errno));
417 return -1;
418 }
419 socket_set_nonblock(ads->fd);
420
421 /* Invoke FD creation callback (if required) */
422 if (cb != NULL) {
423 cb(ads, opaque);
424 }
425
426 /* Synchronously connect to it. */
427 ads->socket_status = ADS_CONNECTING;
428 iolooper_add_write(_ads_io_looper(ads), ads->fd);
429 res = socket_connect(ads->fd, &ads->address);
430 while (res < 0 && errno == EINTR) {
431 res = socket_connect(ads->fd, &ads->address);
432 }
433
434 if (res && (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN)) {
435 /* Connection is delayed. Wait for it until timeout expires. */
436 res = iolooper_wait_absolute(_ads_io_looper(ads), ads->deadline);
437 if (res > 0) {
438 /* Pick up on possible connection error. */
439 errno = socket_get_error(ads->fd);
440 res = (errno == 0) ? 0 : -1;
441 } else {
442 res = -1;
443 }
444 }
445 iolooper_del_write(_ads_io_looper(ads), ads->fd);
446
447 if (res == 0) {
448 D("Channel '%s'@%d is connected", _ads_id_str(ads), _ads_port(ads));
449 /* Socket is connected. Now register it with the server. */
450 ads->socket_status = ADS_CONNECTED;
451 res = _android_dev_socket_register(ads);
452 } else {
453 D("Unable to connect channel '%s' to port %d: %s",
454 _ads_id_str(ads), _ads_port(ads), strerror(errno));
455 }
456
457 if (res) {
458 _android_dev_socket_disconnect(ads);
459 }
460
461 return res;
462 }
463
464 static int
_android_dev_socket_register(AndroidDevSocket * ads)465 _android_dev_socket_register(AndroidDevSocket* ads)
466 {
467 /* Make sure that socket is connected. */
468 if (ads->socket_status < ADS_CONNECTED) {
469 D("Attempt to register a disconnected channel '%s'@%d",
470 _ads_id_str(ads), _ads_port(ads));
471 errno = ECONNRESET;
472 return -1;
473 }
474
475 /* Register this socket accordingly to its type. */
476 const char* reg_str = _ads_id_str(ads);
477 int res = _android_dev_socket_send(ads, reg_str, strlen(reg_str) + 1);
478 if (res > 0) {
479 /* Receive reply. Note that according to the protocol, the server should
480 * reply to channel registration with 'ok', or 'ko' (just like with queries),
481 * so we can use query reply reader here. */
482 char reply[256];
483 res = _android_dev_socket_read_response(ads, reply, sizeof(reply));
484 if (res >= 0) {
485 /* Socket is now registered. */
486 ads->socket_status = ADS_REGISTERED;
487 D("Channel '%s'@%d is registered", _ads_id_str(ads), _ads_port(ads));
488 res = 0;
489 } else {
490 if (errno == 0) {
491 /* 'ko' condition */
492 D("Device failed registration of channel '%s'@%d: %s",
493 _ads_id_str(ads), _ads_port(ads), reply);
494 errno = EINVAL;
495 } else {
496 D("I/O failure while registering channel '%s'@%d: %s",
497 _ads_id_str(ads), _ads_port(ads), strerror(errno));
498 }
499 res = -1;
500 }
501 } else {
502 D("Unable to send registration query for channel '%s'@%d: %s",
503 _ads_id_str(ads), _ads_port(ads), strerror(errno));
504 res = -1;
505 }
506
507 return res;
508 }
509
510 static void
_android_dev_socket_disconnect(AndroidDevSocket * ads)511 _android_dev_socket_disconnect(AndroidDevSocket* ads)
512 {
513 /* Preserve errno */
514 const int save_error = errno;
515 if (ads->socket_status != ADS_DISCONNECTED) {
516 /* Reset I/O looper for this socket. */
517 iolooper_modify(_ads_io_looper(ads), ads->fd,
518 IOLOOPER_READ | IOLOOPER_WRITE, 0);
519
520 /* Mark as disconnected. */
521 ads->socket_status = ADS_DISCONNECTED;
522
523 /* Close socket. */
524 if (ads->fd >= 0) {
525 socket_close(ads->fd);
526 ads->fd = -1;
527 }
528 }
529 errno = save_error;
530 }
531
532 static int
_android_dev_socket_send(AndroidDevSocket * ads,const char * buff,int to_send)533 _android_dev_socket_send(AndroidDevSocket* ads, const char* buff, int to_send)
534 {
535 int sent = 0;
536
537 /* Make sure that socket is connected. */
538 if (ads->socket_status < ADS_CONNECTED) {
539 D("Attempt to send via disconnected channel '%s'@%d",
540 _ads_id_str(ads), _ads_port(ads));
541 errno = ECONNRESET;
542 return -1;
543 }
544
545 iolooper_add_write(_ads_io_looper(ads), ads->fd);
546 do {
547 int res = socket_send(ads->fd, buff + sent, to_send - sent);
548 if (res == 0) {
549 /* Disconnection. */
550 errno = ECONNRESET;
551 sent = -1;
552 break;
553 }
554
555 if (res < 0) {
556 if (errno == EINTR) {
557 /* loop on EINTR */
558 continue;
559 }
560
561 if (errno == EWOULDBLOCK || errno == EAGAIN) {
562 res = iolooper_wait_absolute(_ads_io_looper(ads), ads->deadline);
563 if (res > 0) {
564 /* Ready to write. */
565 continue;
566 }
567 }
568 sent = -1;
569 break;
570 }
571 sent += res;
572 } while (sent < to_send);
573 iolooper_del_write(_ads_io_looper(ads), ads->fd);
574
575 /* In case of an I/O failure we have to invoke failure callback. Note that we
576 * report I/O failures only on registered sockets. */
577 if (sent < 0) {
578 D("I/O error while sending data via channel '%s'@%d: %s",
579 _ads_id_str(ads), _ads_port(ads), strerror(errno));
580
581 if (ads->ad->on_io_failure != NULL && ads->socket_status > ADS_CONNECTED) {
582 const char save_error = errno;
583 ads->ad->on_io_failure(ads->opaque, ads->ad, save_error);
584 errno = save_error;
585 }
586 }
587
588 return sent;
589 }
590
591 static int
_android_dev_socket_recv(AndroidDevSocket * ads,char * buf,int bufsize)592 _android_dev_socket_recv(AndroidDevSocket* ads, char* buf, int bufsize)
593 {
594 int recvd = 0;
595
596 /* Make sure that socket is connected. */
597 if (ads->socket_status < ADS_CONNECTED) {
598 D("Attempt to receive from disconnected channel '%s'@%d",
599 _ads_id_str(ads), _ads_port(ads));
600 errno = ECONNRESET;
601 return -1;
602 }
603
604 iolooper_add_read(_ads_io_looper(ads), ads->fd);
605 do {
606 int res = socket_recv(ads->fd, buf + recvd, bufsize - recvd);
607 if (res == 0) {
608 /* Disconnection. */
609 errno = ECONNRESET;
610 recvd = -1;
611 break;
612 }
613
614 if (res < 0) {
615 if (errno == EINTR) {
616 /* loop on EINTR */
617 continue;
618 }
619
620 if (errno == EWOULDBLOCK || errno == EAGAIN) {
621 res = iolooper_wait_absolute(_ads_io_looper(ads), ads->deadline);
622 if (res > 0) {
623 /* Ready to read. */
624 continue;
625 }
626 }
627 recvd = -1;
628 break;
629 }
630 recvd += res;
631 } while (recvd < bufsize);
632 iolooper_del_read(_ads_io_looper(ads), ads->fd);
633
634 /* In case of an I/O failure we have to invoke failure callback. Note that we
635 * report I/O failures only on registered sockets. */
636 if (recvd < 0) {
637 D("I/O error while receiving from channel '%s'@%d: %s",
638 _ads_id_str(ads), _ads_port(ads), strerror(errno));
639
640 if (ads->ad->on_io_failure != NULL && ads->socket_status > ADS_CONNECTED) {
641 const char save_error = errno;
642 ads->ad->on_io_failure(ads->opaque, ads->ad, save_error);
643 errno = save_error;
644 }
645 }
646
647 return recvd;
648 }
649
650 static int
_android_dev_socket_read_string(AndroidDevSocket * ads,char * str,int strsize)651 _android_dev_socket_read_string(AndroidDevSocket* ads, char* str, int strsize)
652 {
653 int n;
654
655 /* Char by char read from the socket, until zero-terminator is read. */
656 for (n = 0; n < strsize; n++) {
657 if (_android_dev_socket_recv(ads, str + n, 1) > 0) {
658 if (str[n] == '\0') {
659 /* Done. */
660 return n + 1; /* Including zero-terminator. */
661 }
662 } else {
663 /* I/O error. */
664 return -1;
665 }
666 }
667
668 /* Buffer was too small. Report that by setting errno to ENOMEM. */
669 D("Buffer %d is too small to receive a string from channel '%s'@%d",
670 strsize, _ads_id_str(ads), _ads_port(ads));
671 errno = ENOMEM;
672 return -1;
673 }
674
675 static int
_android_dev_socket_read_response(AndroidDevSocket * ads,char * data,int datasize)676 _android_dev_socket_read_response(AndroidDevSocket* ads, char* data, int datasize)
677 {
678 int n, res;
679 int success = 0;
680 int failure = 0;
681 int bad_format = 0;
682 char ok[4];
683
684 *data = '\0';
685
686 /* Char by char read from the socket, until ok/ko is read. */
687 for (n = 0; n < 2; n++) {
688 res = _android_dev_socket_recv(ads, ok + n, 1);
689 if (res > 0) {
690 if (ok[n] == '\0') {
691 /* EOS is unexpected here! */
692 D("Bad query reply format on channel '%s'@%d: '%s' is too short.",
693 _ads_id_str(ads), _ads_port(ads), ok);
694 errno = EINVAL;
695 return -1;
696 }
697 } else {
698 /* I/O error. */
699 return -1;
700 }
701 }
702
703 /* Next character must be either ':', or '\0' */
704 res = _android_dev_socket_recv(ads, ok + n, 1);
705 if (res <= 0) {
706 /* I/O error. */
707 return -1;
708 }
709
710 /*
711 * Verify format.
712 */
713
714 /* Check ok / ko */
715 success = memcmp(ok, "ok", 2) == 0;
716 failure = memcmp(ok, "ko", 2) == 0;
717
718 /* Check the prefix: 'ok'|'ko' & ':'|'\0' */
719 if ((success || failure) && (ok[n] == '\0' || ok[n] == ':')) {
720 /* Format is good. */
721 if (ok[n] == '\0') {
722 /* We're done: no extra data in response. */
723 errno = 0;
724 return success ? 0 : -1;
725 }
726 /* Reset buffer offset, so we will start to read the remaining query
727 * data to the beginning of the supplied buffer. */
728 n = 0;
729 } else {
730 /* Bad format. Lets move what we've read to the main buffer, and
731 * continue filling it in. */
732 bad_format = 1;
733 n++;
734 memcpy(data, ok, n);
735 }
736
737 /* Read the remainder of reply to the supplied data buffer. */
738 res = _android_dev_socket_read_string(ads, data + n, datasize - n);
739 if (res < 0) {
740 return res;
741 }
742
743 /* Lets see if format was bad */
744 if (bad_format) {
745 D("Bad query reply format on channel '%s'@%d: %s.",
746 _ads_id_str(ads), _ads_port(ads), data);
747 errno = EINVAL;
748 return -1;
749 } else {
750 errno = 0;
751 return success ? n : -1;
752 }
753 }
754
755 /********************************************************************************
756 * Query socket declarations
757 *******************************************************************************/
758
759 /* Initializes query socket descriptor.
760 * Param:
761 * adsquery - Socket descriptor to initialize.
762 * opaque - An opaque pointer to associate with the socket. Typicaly it's the
763 * same pointer that is associated with AndroidDevice instance.
764 * ad - Android device descriptor that owns the socket.
765 * port - TCP socket port.
766 */
767 static int _android_query_socket_init(AndroidQuerySocket* adsquery,
768 void* opaque,
769 AndroidDevice* ad,
770 int port);
771
772 /* Destroys query socket descriptor. */
773 static void _android_query_socket_destroy(AndroidQuerySocket* adsquery);
774
775 /* Synchronously connects the query socket, and registers it with the server.
776 * Param:
777 * adsquery - Descriptor for the query socket to connect. Must have 'deadline'
778 * field properly setup.
779 * cb - Callback to invoke when socket connection is completed. Can be NULL.
780 * Return:
781 * Zero on success, or non-zero on failure.
782 */
783 static int _android_query_socket_connect(AndroidQuerySocket* adsquery);
784
785 /* Disconnects the query socket. */
786 static void _android_query_socket_disconnect(AndroidQuerySocket* adsquery);
787
788 /********************************************************************************
789 * Query socket implementation
790 *******************************************************************************/
791
792 static int
_android_query_socket_init(AndroidQuerySocket * adsquery,void * opaque,AndroidDevice * ad,int port)793 _android_query_socket_init(AndroidQuerySocket* adsquery,
794 void* opaque,
795 AndroidDevice* ad,
796 int port)
797 {
798 return _android_dev_socket_init(&adsquery->dev_socket, opaque, ad, port,
799 ADS_TYPE_QUERY);
800 }
801
802 static void
_android_query_socket_destroy(AndroidQuerySocket * adsquery)803 _android_query_socket_destroy(AndroidQuerySocket* adsquery)
804 {
805 _android_query_socket_disconnect(adsquery);
806 _android_dev_socket_destroy(&adsquery->dev_socket);
807 }
808
809 static int
_android_query_socket_connect(AndroidQuerySocket * adsquery)810 _android_query_socket_connect(AndroidQuerySocket* adsquery)
811 {
812 return _android_dev_socket_connect(&adsquery->dev_socket, NULL, NULL);
813 }
814
815 static void
_android_query_socket_disconnect(AndroidQuerySocket * adsquery)816 _android_query_socket_disconnect(AndroidQuerySocket* adsquery)
817 {
818 _android_dev_socket_disconnect(&adsquery->dev_socket);
819 }
820
821 /********************************************************************************
822 * Events socket declarations
823 *******************************************************************************/
824
825 /* Initializes event socket descriptor.
826 * Param:
827 * adsevent - Socket descriptor to initialize.
828 * opaque - An opaque pointer to associate with the socket. Typicaly it's the
829 * same pointer that is associated with AndroidDevice instance.
830 * ad - Android device descriptor that owns the socket.
831 * port - TCP socket port.
832 */
833 static int _android_event_socket_init(AndroidEventSocket* adsevent,
834 void* opaque,
835 AndroidDevice* ad,
836 int port);
837
838 /* Destroys the event socket descriptor. */
839 static void _android_event_socket_destroy(AndroidEventSocket* adsevent);
840
841 /* Synchronously connects event socket.
842 * Param:
843 * adsevent - Descriptor for the event socket to connect. Must have 'deadline'
844 * field properly setup.
845 * Return:
846 * Zero on success, or non-zero on failure.
847 */
848 static int _android_event_socket_connect_sync(AndroidEventSocket* adsevent);
849
850 /* Initiates asynchronous event socket connection.
851 * Param:
852 * adsevent - Descriptor for the event socket to connect. Must have 'deadline'
853 * field properly setup.
854 * cb - Callback to invoke when socket connection is completed. Can be NULL.
855 * Return:
856 * Zero on success, or non-zero on failure.
857 */
858 static int _android_event_socket_connect_async(AndroidEventSocket* adsevent,
859 ads_socket_connected_cb cb);
860
861 /* Disconnects the event socket. */
862 static void _android_event_socket_disconnect(AndroidEventSocket* adsevent);
863
864 /* Initiates listening on the event socket.
865 * Param:
866 * adsevent - Descriptor for the event socket to listen on.
867 * str, strsize - Buffer where to read the string.
868 * cb - A callback to call when the event string is read. Can be NULL.
869 * Return:
870 * Zero on success, or non-zero on failure.
871 */
872 static int _android_event_socket_listen(AndroidEventSocket* adsevent,
873 char* str,
874 int strsize,
875 event_cb cb);
876
877 /* Asynchronously sends data via event socket.
878 * Param:
879 * adsevent - Descriptor for the event socket to send data to.
880 * data, size - Buffer containing data to send.
881 * free_on_close - A boolean flag indicating whether the data buffer should be
882 * freed upon data transfer completion.
883 * cb - Callback to invoke when data transfer is completed.
884 * opaque - An opaque pointer to pass to the transfer completion callback.
885 */
886 static int _android_event_socket_send(AndroidEventSocket* adsevent,
887 void* data,
888 int size,
889 int free_on_close,
890 async_send_cb cb,
891 void* opaque);
892
893 /* Cancels all asynchronous data transfers on the event socket.
894 * Param:
895 * adsevent - Descriptor for the event socket to cancel data transfer.
896 * reason - Reason for the cancellation.
897 */
898 static void _android_event_socket_cancel_send(AndroidEventSocket* adsevent,
899 ATResult reason);
900
901 /* Event socket's asynchronous I/O looper callback.
902 * Param:
903 * opaque - AndroidEventSocket instance.
904 * fd - Socket's FD.
905 * events - I/O type bitsmask (read | write).
906 */
907 static void _on_event_socket_io(void* opaque, int fd, unsigned events);
908
909 /* Callback that is invoked when asynchronous event socket connection is
910 * completed. */
911 static void _on_event_socket_connected(AndroidEventSocket* adsevent, int failure);
912
913 /* Callback that is invoked when an event is received from the device. */
914 static void _on_event_received(AndroidEventSocket* adsevent);
915
916 /* Gets I/O looper for asynchronous I/O on event socket. */
917 AINLINED Looper*
_aes_looper(AndroidEventSocket * adsevent)918 _aes_looper(AndroidEventSocket* adsevent)
919 {
920 return adsevent->dev_socket.ad->looper;
921 }
922
923 /********************************************************************************
924 * Events socket implementation
925 *******************************************************************************/
926
927 static int
_android_event_socket_init(AndroidEventSocket * adsevent,void * opaque,AndroidDevice * ad,int port)928 _android_event_socket_init(AndroidEventSocket* adsevent,
929 void* opaque,
930 AndroidDevice* ad,
931 int port)
932 {
933 return _android_dev_socket_init(&adsevent->dev_socket, opaque, ad, port,
934 ADS_TYPE_EVENT);
935 }
936
937 static void
_android_event_socket_destroy(AndroidEventSocket * adsevent)938 _android_event_socket_destroy(AndroidEventSocket* adsevent)
939 {
940 _android_event_socket_disconnect(adsevent);
941 _android_dev_socket_destroy(&adsevent->dev_socket);
942 }
943
944 /* A callback invoked when file descriptor is created for the event socket.
945 * We use this callback to initialize the event socket for async I/O right after
946 * the FD has been created.
947 */
948 static void
_on_event_fd_created(AndroidDevSocket * ads,void * opaque)949 _on_event_fd_created(AndroidDevSocket* ads, void* opaque)
950 {
951 AndroidEventSocket* adsevent = (AndroidEventSocket*)opaque;
952 /* Prepare for async I/O on the event socket. */
953 loopIo_init(adsevent->io, _aes_looper(adsevent), ads->fd,
954 _on_event_socket_io, adsevent);
955 }
956
957 static int
_android_event_socket_connect_sync(AndroidEventSocket * adsevent)958 _android_event_socket_connect_sync(AndroidEventSocket* adsevent)
959 {
960 return _android_dev_socket_connect(&adsevent->dev_socket,
961 _on_event_fd_created, adsevent);
962 }
963
964 static int
_android_event_socket_connect_async(AndroidEventSocket * adsevent,ads_socket_connected_cb cb)965 _android_event_socket_connect_async(AndroidEventSocket* adsevent,
966 ads_socket_connected_cb cb)
967 {
968 AsyncStatus status;
969 AndroidDevSocket* ads = &adsevent->dev_socket;
970
971 /* Create asynchronous socket. */
972 ads->fd = socket_create_inet(SOCKET_STREAM);
973 if (ads->fd < 0) {
974 D("Unable to create socket for channel '%s'@%d: %s",
975 _ads_id_str(ads), _ads_port(ads), strerror(errno));
976 if (cb != NULL) {
977 cb(ads->opaque, ads, errno);
978 }
979 return -1;
980 }
981 socket_set_nonblock(ads->fd);
982
983 /* Prepare for async I/O on the event socket. */
984 loopIo_init(adsevent->io, _aes_looper(adsevent), ads->fd,
985 _on_event_socket_io, adsevent);
986
987 /* Try to connect. */
988 ads->socket_status = ADS_CONNECTING;
989 adsevent->on_connected = cb;
990 status = asyncConnector_init(adsevent->connector, &ads->address, adsevent->io);
991 switch (status) {
992 case ASYNC_COMPLETE:
993 /* We're connected to the device socket. */
994 ads->socket_status = ADS_CONNECTED;
995 _on_event_socket_connected(adsevent, 0);
996 break;
997 case ASYNC_ERROR:
998 _on_event_socket_connected(adsevent, errno);
999 break;
1000 case ASYNC_NEED_MORE:
1001 /* Attempt to connect would block, so connection competion is
1002 * delegates to the looper's I/O routine. */
1003 default:
1004 break;
1005 }
1006
1007 return 0;
1008 }
1009
1010 static void
_android_event_socket_disconnect(AndroidEventSocket * adsevent)1011 _android_event_socket_disconnect(AndroidEventSocket* adsevent)
1012 {
1013 AndroidDevSocket* ads = &adsevent->dev_socket;
1014
1015 if (ads->socket_status != ADS_DISCONNECTED) {
1016 /* Cancel data transfer. */
1017 _android_event_socket_cancel_send(adsevent, ATR_DISCONNECT);
1018
1019 /* Stop all async I/O. */
1020 loopIo_done(adsevent->io);
1021
1022 /* Disconnect common socket. */
1023 _android_dev_socket_disconnect(ads);
1024 }
1025 }
1026
1027 static int
_android_event_socket_listen(AndroidEventSocket * adsevent,char * str,int strsize,event_cb cb)1028 _android_event_socket_listen(AndroidEventSocket* adsevent,
1029 char* str,
1030 int strsize,
1031 event_cb cb)
1032 {
1033 AsyncStatus status;
1034 AndroidDevSocket* ads = &adsevent->dev_socket;
1035
1036 /* Make sure that device is connected. */
1037 if (ads->socket_status < ADS_CONNECTED) {
1038 D("Attempt to listen on a disconnected channel '%s'@%d",
1039 _ads_id_str(ads), _ads_port(ads));
1040 errno = ECONNRESET;
1041 return -1;
1042 }
1043
1044 /* NOTE: only one reader at any given time! */
1045 adsevent->on_event = cb;
1046 asyncLineReader_init(&adsevent->alr, str, strsize, adsevent->io);
1047 /* Default EOL for the line reader was '\n'. */
1048 asyncLineReader_setEOL(&adsevent->alr, '\0');
1049 status = asyncLineReader_read(&adsevent->alr);
1050 if (status == ASYNC_COMPLETE) {
1051 /* Data has been transferred immediately. Do the callback here. */
1052 _on_event_received(adsevent);
1053 } else if (status == ASYNC_ERROR) {
1054 D("Error while listening on channel '%s'@%d: %s",
1055 _ads_id_str(ads), _ads_port(ads), strerror(errno));
1056 /* There is one special failure here, when buffer was too small to
1057 * contain the entire string. This is not an I/O, but rather a
1058 * protocol error. So we don't report it to the I/O failure
1059 * callback. */
1060 if (errno == ENOMEM) {
1061 _on_event_received(adsevent);
1062 } else {
1063 if (ads->ad->on_io_failure != NULL) {
1064 ads->ad->on_io_failure(ads->ad->opaque, ads->ad, errno);
1065 }
1066 }
1067 return -1;
1068 }
1069 return 0;
1070 }
1071
1072 static int
_android_event_socket_send(AndroidEventSocket * adsevent,void * data,int size,int free_on_close,async_send_cb cb,void * opaque)1073 _android_event_socket_send(AndroidEventSocket* adsevent,
1074 void* data,
1075 int size,
1076 int free_on_close,
1077 async_send_cb cb,
1078 void* opaque)
1079 {
1080 /* Create data transfer descriptor, and place it at the end of the list. */
1081 AsyncSendBuffer* const desc =
1082 _async_send_buffer_create(data, size, free_on_close, cb, opaque);
1083 AsyncSendBuffer** place = &adsevent->send_pending;
1084 while (*place != NULL) {
1085 place = &((*place)->next);
1086 }
1087 *place = desc;
1088
1089 /* We're ready to transfer data. */
1090 loopIo_wantWrite(adsevent->io);
1091
1092 return 0;
1093 }
1094
1095 static void
_android_event_socket_cancel_send(AndroidEventSocket * adsevent,ATResult reason)1096 _android_event_socket_cancel_send(AndroidEventSocket* adsevent, ATResult reason)
1097 {
1098 while (adsevent->send_pending != NULL) {
1099 AsyncSendBuffer* const to_cancel = adsevent->send_pending;
1100 adsevent->send_pending = to_cancel->next;
1101 _async_send_buffer_complete(to_cancel, reason);
1102 }
1103 loopIo_dontWantWrite(adsevent->io);
1104 }
1105
1106 static void
_on_event_socket_io(void * opaque,int fd,unsigned events)1107 _on_event_socket_io(void* opaque, int fd, unsigned events)
1108 {
1109 AsyncStatus status;
1110 AndroidEventSocket* adsevent = (AndroidEventSocket*)opaque;
1111 AndroidDevSocket* ads = &adsevent->dev_socket;
1112
1113 /* Lets see if we're still wating on a connection to occur. */
1114 if (ads->socket_status == ADS_CONNECTING) {
1115 /* Complete socket connection. */
1116 status = asyncConnector_run(adsevent->connector);
1117 if (status == ASYNC_COMPLETE) {
1118 /* We're connected to the device socket. */
1119 ads->socket_status = ADS_CONNECTED;
1120 D("Channel '%s'@%d is connected asynchronously",
1121 _ads_id_str(ads), _ads_port(ads));
1122 _on_event_socket_connected(adsevent, 0);
1123 } else if (status == ASYNC_ERROR) {
1124 _on_event_socket_connected(adsevent, adsevent->connector->error);
1125 }
1126 return;
1127 }
1128
1129 /*
1130 * Device is connected. Continue with the data transfer.
1131 */
1132
1133 if ((events & LOOP_IO_READ) != 0) {
1134 /* Continue reading data. */
1135 status = asyncLineReader_read(&adsevent->alr);
1136 if (status == ASYNC_COMPLETE) {
1137 errno = 0;
1138 _on_event_received(adsevent);
1139 } else if (status == ASYNC_ERROR) {
1140 D("I/O failure while reading from channel '%s'@%d: %s",
1141 _ads_id_str(ads), _ads_port(ads), strerror(errno));
1142 /* There is one special failure here, when buffer was too small to
1143 * contain the entire string. This is not an I/O, but rather a
1144 * protocol error. So we don't report it to the I/O failure
1145 * callback. */
1146 if (errno == ENOMEM) {
1147 _on_event_received(adsevent);
1148 } else {
1149 if (ads->ad->on_io_failure != NULL) {
1150 ads->ad->on_io_failure(ads->ad->opaque, ads->ad, errno);
1151 }
1152 }
1153 }
1154 }
1155
1156 if ((events & LOOP_IO_WRITE) != 0) {
1157 while (adsevent->send_pending != NULL) {
1158 AsyncSendBuffer* to_send = adsevent->send_pending;
1159 const int offset = to_send->data_size - to_send->data_remaining;
1160 const int sent = socket_send(ads->fd, to_send->data + offset,
1161 to_send->data_remaining);
1162 if (sent < 0) {
1163 if (errno == EWOULDBLOCK) {
1164 /* Try again later. */
1165 return;
1166 } else {
1167 /* An error has occured. */
1168 _android_event_socket_cancel_send(adsevent, ATR_IO_ERROR);
1169 if (ads->ad->on_io_failure != NULL) {
1170 ads->ad->on_io_failure(ads->ad->opaque, ads->ad, errno);
1171 }
1172 return;
1173 }
1174 } else if (sent == 0) {
1175 /* Disconnect condition. */
1176 _android_event_socket_cancel_send(adsevent, ATR_DISCONNECT);
1177 if (ads->ad->on_io_failure != NULL) {
1178 ads->ad->on_io_failure(ads->ad->opaque, ads->ad, errno);
1179 }
1180 return;
1181 } else if (sent == to_send->data_remaining) {
1182 /* All data is sent. */
1183 errno = 0;
1184 adsevent->send_pending = to_send->next;
1185 _async_send_buffer_complete(to_send, ATR_SUCCESS);
1186 } else {
1187 /* Chunk is sent. */
1188 to_send->data_remaining -= sent;
1189 return;
1190 }
1191 }
1192 loopIo_dontWantWrite(adsevent->io);
1193 }
1194 }
1195
1196 static void
_on_event_socket_connected(AndroidEventSocket * adsevent,int failure)1197 _on_event_socket_connected(AndroidEventSocket* adsevent, int failure)
1198 {
1199 int res;
1200 AndroidDevSocket* ads = &adsevent->dev_socket;
1201
1202 if (failure) {
1203 _android_event_socket_disconnect(adsevent);
1204 if (adsevent->on_connected != NULL) {
1205 adsevent->on_connected(ads->opaque, ads, failure);
1206 }
1207 return;
1208 }
1209
1210 /* Complete event socket connection by identifying it as "event" socket with
1211 * the application. */
1212 ads->socket_status = ADS_CONNECTED;
1213 res = _android_dev_socket_register(ads);
1214
1215 if (res) {
1216 const int save_error = errno;
1217 _android_event_socket_disconnect(adsevent);
1218 errno = save_error;
1219 }
1220
1221 /* Notify callback about connection completion. */
1222 if (adsevent->on_connected != NULL) {
1223 if (res) {
1224 adsevent->on_connected(ads->opaque, ads, errno);
1225 } else {
1226 adsevent->on_connected(ads->opaque, ads, 0);
1227 }
1228 }
1229 }
1230
1231 static void
_on_event_received(AndroidEventSocket * adsevent)1232 _on_event_received(AndroidEventSocket* adsevent)
1233 {
1234 if (adsevent->on_event != NULL) {
1235 AndroidDevice* ad = adsevent->dev_socket.ad;
1236 adsevent->on_event(ad->opaque, ad, (char*)adsevent->alr.buffer,
1237 adsevent->alr.pos);
1238 }
1239 }
1240
1241 /********************************************************************************
1242 * Android device connection
1243 *******************************************************************************/
1244
1245 /* Callback that is invoked when event socket is connected and registered as part
1246 * of the _android_device_connect_async API.
1247 * Param:
1248 * opaque - Opaque pointer associated with AndroidDevice instance.
1249 * ads - Common socket descriptor for the event socket.
1250 * failure - If zero connection has succeeded, otherwise contains 'errno'-reason
1251 * for connection failure.
1252 */
1253 static void
_on_android_device_connected_async(void * opaque,AndroidDevSocket * ads,int failure)1254 _on_android_device_connected_async(void* opaque,
1255 AndroidDevSocket* ads,
1256 int failure)
1257 {
1258 int res;
1259 AndroidDevice* ad = ads->ad;
1260
1261 if (failure) {
1262 /* Depending on the failure code we will either retry, or bail out. */
1263 switch (failure) {
1264 case EPIPE:
1265 case EAGAIN:
1266 case EINPROGRESS:
1267 case EALREADY:
1268 case EHOSTUNREACH:
1269 case EHOSTDOWN:
1270 case ECONNREFUSED:
1271 case ESHUTDOWN:
1272 case ENOTCONN:
1273 case ECONNRESET:
1274 case ECONNABORTED:
1275 case ENETRESET:
1276 case ENETUNREACH:
1277 case ENETDOWN:
1278 case EBUSY:
1279 #if !defined(_DARWIN_C_SOURCE) && !defined(_WIN32)
1280 case ERESTART:
1281 case ECOMM:
1282 case ENONET:
1283 #endif /* !_DARWIN_C_SOURCE && !_WIN32 */
1284 /* Device is not available / reachable at the moment.
1285 * Retry connection later. */
1286 loopTimer_startRelative(ad->timer, ADS_RETRY_CONNECTION_TIMEOUT);
1287 return;
1288 default:
1289 D("Failed to asynchronously connect channel '%s':%d %s",
1290 _ads_id_str(ads), _ads_port(ads), strerror(errno));
1291 if (ad->on_connected != NULL) {
1292 ad->on_connected(ad->opaque, ad, failure);
1293 }
1294 break;
1295 }
1296 return;
1297 }
1298
1299 /* Event socket is connected. Connect the query socket now. Give it 5
1300 * seconds to connect. */
1301 _ads_set_deadline(&ad->query_socket.dev_socket, 5000);
1302 res = _android_query_socket_connect(&ad->query_socket);
1303 if (res == 0) {
1304 /* Query socket is connected. */
1305 if (ad->on_connected != NULL) {
1306 ad->on_connected(ad->opaque, ad, 0);
1307 }
1308 } else {
1309 /* If connection completion has failed - disconnect the sockets. */
1310 _android_event_socket_disconnect(&ad->event_socket);
1311 _android_query_socket_disconnect(&ad->query_socket);
1312
1313 if (ad->on_connected != NULL) {
1314 ad->on_connected(ad->opaque, ad, errno);
1315 }
1316 }
1317 }
1318
1319 static void
_on_timer(void * opaque)1320 _on_timer(void* opaque)
1321 {
1322 /* Retry the connection. */
1323 AndroidDevice* ad = (AndroidDevice*)opaque;
1324 android_device_connect_async(ad, ad->on_connected);
1325 }
1326
1327 /* Destroys and frees the descriptor. */
1328 static void
_android_device_free(AndroidDevice * ad)1329 _android_device_free(AndroidDevice* ad)
1330 {
1331 if (ad != NULL) {
1332 _android_event_socket_destroy(&ad->event_socket);
1333 _android_query_socket_destroy(&ad->query_socket);
1334
1335 /* Delete asynchronous I/O looper. */
1336 if (ad->looper != NULL ) {
1337 loopTimer_done(ad->timer);
1338 looper_free(ad->looper);
1339 }
1340
1341 /* Delete synchronous I/O looper. */
1342 if (ad->io_looper != NULL) {
1343 iolooper_reset(ad->io_looper);
1344 iolooper_free(ad->io_looper);
1345 }
1346
1347 AFREE(ad);
1348 }
1349 }
1350
1351 /********************************************************************************
1352 * Android device API
1353 *******************************************************************************/
1354
1355 AndroidDevice*
android_device_init(void * opaque,int port,io_failure_cb on_io_failure)1356 android_device_init(void* opaque, int port, io_failure_cb on_io_failure)
1357 {
1358 int res;
1359 AndroidDevice* ad;
1360
1361 ANEW0(ad);
1362
1363 ad->opaque = opaque;
1364 ad->on_io_failure = on_io_failure;
1365
1366 /* Create I/O looper for synchronous I/O on the device. */
1367 ad->io_looper = iolooper_new();
1368 if (ad->io_looper == NULL) {
1369 E("Unable to create synchronous I/O looper for android device.");
1370 _android_device_free(ad);
1371 return NULL;
1372 }
1373
1374 /* Create a looper for asynchronous I/O on the device. */
1375 ad->looper = looper_newCore();
1376 if (ad->looper != NULL) {
1377 /* Create a timer that will be used for connection retries. */
1378 loopTimer_init(ad->timer, ad->looper, _on_timer, ad);
1379 } else {
1380 E("Unable to create asynchronous I/O looper for android device.");
1381 _android_device_free(ad);
1382 return NULL;
1383 }
1384
1385 /* Init query socket. */
1386 res = _android_query_socket_init(&ad->query_socket, opaque, ad, port);
1387 if (res) {
1388 _android_device_free(ad);
1389 return NULL;
1390 }
1391
1392 /* Init event socket. */
1393 res = _android_event_socket_init(&ad->event_socket, opaque, ad, port);
1394 if (res) {
1395 _android_device_free(ad);
1396 return NULL;
1397 }
1398
1399 return ad;
1400 }
1401
1402 void
android_device_destroy(AndroidDevice * ad)1403 android_device_destroy(AndroidDevice* ad)
1404 {
1405 if (ad != NULL) {
1406 _android_device_free(ad);
1407 }
1408 }
1409
1410 int
android_device_connect_sync(AndroidDevice * ad,int to)1411 android_device_connect_sync(AndroidDevice* ad, int to)
1412 {
1413 int res;
1414
1415 /* Setup deadline for the connections. */
1416 _ads_set_deadline(&ad->query_socket.dev_socket, to);
1417 ad->event_socket.dev_socket.deadline = ad->query_socket.dev_socket.deadline;
1418
1419 /* Connect the query socket first. */
1420 res = _android_query_socket_connect(&ad->query_socket);
1421 if (!res) {
1422 /* Connect to the event socket next. */
1423 res = _android_event_socket_connect_sync(&ad->event_socket);
1424 }
1425
1426 return res;
1427 }
1428
1429 int
android_device_connect_async(AndroidDevice * ad,device_connected_cb on_connected)1430 android_device_connect_async(AndroidDevice* ad, device_connected_cb on_connected)
1431 {
1432 /* No deadline for async connections. */
1433 ad->query_socket.dev_socket.deadline = DURATION_INFINITE;
1434 ad->event_socket.dev_socket.deadline = DURATION_INFINITE;
1435
1436 /* Connect to the event socket first, and delegate query socket connection
1437 * into callback invoked when event socket is connected. NOTE: In case of
1438 * failure 'on_connected' callback has already been called from
1439 * _on_android_device_connected_async routine. */
1440 ad->on_connected = on_connected;
1441 return _android_event_socket_connect_async(&ad->event_socket,
1442 _on_android_device_connected_async);
1443 }
1444
1445 void
android_device_disconnect(AndroidDevice * ad)1446 android_device_disconnect(AndroidDevice* ad)
1447 {
1448 _android_event_socket_disconnect(&ad->event_socket);
1449 _android_query_socket_disconnect(&ad->query_socket);
1450 }
1451
1452 int
android_device_query(AndroidDevice * ad,const char * query,char * buff,size_t buffsize,int to)1453 android_device_query(AndroidDevice* ad,
1454 const char* query,
1455 char* buff,
1456 size_t buffsize,
1457 int to)
1458 {
1459 int res;
1460
1461 /* Setup deadline for the query. */
1462 _ads_set_deadline(&ad->query_socket.dev_socket, to);
1463
1464 /* Send the query. */
1465 res = _android_dev_socket_send(&ad->query_socket.dev_socket, query,
1466 strlen(query) + 1);
1467 if (res > 0) {
1468 /* Receive the response. */
1469 res = _android_dev_socket_read_response(&ad->query_socket.dev_socket,
1470 buff, buffsize);
1471 return (res >= 0) ? 0 : -1;
1472 }
1473
1474 return -1;
1475 }
1476
1477 int
android_device_start_query(AndroidDevice * ad,const char * query,int to)1478 android_device_start_query(AndroidDevice* ad, const char* query, int to)
1479 {
1480 int res;
1481
1482 /* Setup deadline for the query. */
1483 _ads_set_deadline(&ad->query_socket.dev_socket, to);
1484
1485 /* Send the query header. */
1486 res = _android_dev_socket_send(&ad->query_socket.dev_socket, query,
1487 strlen(query) + 1);
1488 return (res > 0) ? 0 : -1;
1489 }
1490
1491 int
android_device_send_query_data(AndroidDevice * ad,const void * data,int size)1492 android_device_send_query_data(AndroidDevice* ad, const void* data, int size)
1493 {
1494 return _android_dev_socket_send(&ad->query_socket.dev_socket, data, size);
1495 }
1496
1497 int
android_device_complete_query(AndroidDevice * ad,char * buff,size_t buffsize)1498 android_device_complete_query(AndroidDevice* ad, char* buff, size_t buffsize)
1499 {
1500 /* Receive the response to the query. */
1501 const int res = _android_dev_socket_read_response(&ad->query_socket.dev_socket,
1502 buff, buffsize);
1503 return (res >= 0) ? 0 : -1;
1504 }
1505
1506 int
android_device_listen(AndroidDevice * ad,char * buff,int buffsize,event_cb on_event)1507 android_device_listen(AndroidDevice* ad,
1508 char* buff,
1509 int buffsize,
1510 event_cb on_event)
1511 {
1512 return _android_event_socket_listen(&ad->event_socket, buff, buffsize,
1513 on_event);
1514 }
1515
1516 int
android_device_send_async(AndroidDevice * ad,void * data,int size,int free_on_close,async_send_cb cb,void * opaque)1517 android_device_send_async(AndroidDevice* ad,
1518 void* data,
1519 int size,
1520 int free_on_close,
1521 async_send_cb cb,
1522 void* opaque)
1523 {
1524 return _android_event_socket_send(&ad->event_socket, data, size,
1525 free_on_close, cb, opaque);
1526 }
1527