blob: bd49e5253c6c67a8e2ddc48a76fe71478acf3859 [file] [log] [blame]
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001#include <stdint.h>
2#include <stdarg.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <fcntl.h>
6#include <errno.h>
7#include <string.h>
8#include <sys/socket.h>
9#include <termios.h>
10#include <cutils/sockets.h>
11
12/*
The Android Open Source Project6ffae012009-03-18 17:39:43 -070013 * the qemud daemon program is only used within Android as a bridge
The Android Open Source Project52d4c302009-03-03 19:29:09 -080014 * between the emulator program and the emulated system. it really works as
15 * a simple stream multiplexer that works as follows:
16 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070017 * - qemud is started by init following instructions in
18 * /system/etc/init.goldfish.rc (i.e. it is never started on real devices)
19 *
The Android Open Source Project52d4c302009-03-03 19:29:09 -080020 * - qemud communicates with the emulator program through a single serial
21 * port, whose name is passed through a kernel boot parameter
22 * (e.g. android.qemud=ttyS1)
23 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070024 * - qemud binds one unix local stream socket (/dev/socket/qemud, created
25 * by init through /system/etc/init.goldfish.rc).
The Android Open Source Project52d4c302009-03-03 19:29:09 -080026 *
The Android Open Source Project52d4c302009-03-03 19:29:09 -080027 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070028 * emulator <==serial==> qemud <---> /dev/socket/qemud <-+--> client1
29 * |
30 * +--> client2
The Android Open Source Project52d4c302009-03-03 19:29:09 -080031 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070032 * - the special channel index 0 is used by the emulator and qemud only.
33 * other channel numbers correspond to clients. More specifically,
34 * connection are created like this:
The Android Open Source Project52d4c302009-03-03 19:29:09 -080035 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070036 * * the client connects to /dev/socket/qemud
The Android Open Source Project52d4c302009-03-03 19:29:09 -080037 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070038 * * the client sends the service name through the socket, as
39 * <service-name>
The Android Open Source Project52d4c302009-03-03 19:29:09 -080040 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070041 * * qemud creates a "Client" object internally, assigns it an
42 * internal unique channel number > 0, then sends a connection
43 * initiation request to the emulator (i.e. through channel 0):
The Android Open Source Project52d4c302009-03-03 19:29:09 -080044 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070045 * connect:<hxid>:<name>
The Android Open Source Project52d4c302009-03-03 19:29:09 -080046 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070047 * where <name> is the service name, and <hxid> is a 4-hexchar
48 * number corresponding to the channel number.
The Android Open Source Project52d4c302009-03-03 19:29:09 -080049 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070050 * * in case of success, the emulator responds through channel 0
51 * with:
The Android Open Source Project52d4c302009-03-03 19:29:09 -080052 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070053 * ok:connect:<hxid>
54 *
55 * after this, all messages between the client and the emulator
56 * are passed in pass-through mode.
57 *
58 * * if the emulator refuses the service connection, it will
59 * send the following through channel 0:
60 *
61 * ko:connect:<hxid>:reason-for-failure
62 *
63 * * If the client closes the connection, qemud sends the following
64 * to the emulator:
65 *
66 * disconnect:<hxid>
67 *
68 * The same message is the opposite direction if the emulator
69 * chooses to close the connection.
70 *
71 * * any command sent through channel 0 to the emulator that is
72 * not properly recognized will be answered by:
The Android Open Source Project52d4c302009-03-03 19:29:09 -080073 *
74 * ko:unknown command
75 *
76 *
The Android Open Source Project6ffae012009-03-18 17:39:43 -070077 * Internally, the daemon maintains a "Client" object for each client
78 * connection (i.e. accepting socket connection).
The Android Open Source Project52d4c302009-03-03 19:29:09 -080079 */
80
The Android Open Source Project6ffae012009-03-18 17:39:43 -070081/* name of the single control socket used by the daemon */
82#define CONTROL_SOCKET_NAME "qemud"
83
84#define DEBUG 1
85#define T_ACTIVE 0 /* set to 1 to dump traffic */
The Android Open Source Project52d4c302009-03-03 19:29:09 -080086
87#if DEBUG
88# define LOG_TAG "qemud"
89# include <cutils/log.h>
90# define D(...) LOGD(__VA_ARGS__)
91#else
92# define D(...) ((void)0)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070093# define T(...) ((void)0)
94#endif
95
96#if T_ACTIVE
97# define T(...) D(__VA_ARGS__)
98#else
99# define T(...) ((void)0)
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800100#endif
101
102/** UTILITIES
103 **/
104
105static void
106fatal( const char* fmt, ... )
107{
108 va_list args;
109 va_start(args, fmt);
110 fprintf(stderr, "PANIC: ");
111 vfprintf(stderr, fmt, args);
112 fprintf(stderr, "\n" );
113 va_end(args);
114 exit(1);
115}
116
117static void*
118xalloc( size_t sz )
119{
120 void* p;
121
122 if (sz == 0)
123 return NULL;
124
125 p = malloc(sz);
126 if (p == NULL)
127 fatal( "not enough memory" );
128
129 return p;
130}
131
132#define xnew(p) (p) = xalloc(sizeof(*(p)))
133
134static void*
135xalloc0( size_t sz )
136{
137 void* p = xalloc(sz);
138 memset( p, 0, sz );
139 return p;
140}
141
142#define xnew0(p) (p) = xalloc0(sizeof(*(p)))
143
144#define xfree(p) (free((p)), (p) = NULL)
145
146static void*
147xrealloc( void* block, size_t size )
148{
149 void* p = realloc( block, size );
150
151 if (p == NULL && size > 0)
152 fatal( "not enough memory" );
153
154 return p;
155}
156
157#define xrenew(p,count) (p) = xrealloc((p),sizeof(*(p))*(count))
158
159static int
160hex2int( const uint8_t* data, int len )
161{
162 int result = 0;
163 while (len > 0) {
164 int c = *data++;
165 unsigned d;
166
167 result <<= 4;
168 do {
169 d = (unsigned)(c - '0');
170 if (d < 10)
171 break;
172
173 d = (unsigned)(c - 'a');
174 if (d < 6) {
175 d += 10;
176 break;
177 }
178
179 d = (unsigned)(c - 'A');
180 if (d < 6) {
181 d += 10;
182 break;
183 }
184
185 return -1;
186 }
187 while (0);
188
189 result |= d;
190 len -= 1;
191 }
192 return result;
193}
194
195
196static void
197int2hex( int value, uint8_t* to, int width )
198{
199 int nn = 0;
200 static const char hexchars[16] = "0123456789abcdef";
201
202 for ( --width; width >= 0; width--, nn++ ) {
203 to[nn] = hexchars[(value >> (width*4)) & 15];
204 }
205}
206
207static int
208fd_read(int fd, void* to, int len)
209{
210 int ret;
211
212 do {
213 ret = read(fd, to, len);
214 } while (ret < 0 && errno == EINTR);
215
216 return ret;
217}
218
219static int
220fd_write(int fd, const void* from, int len)
221{
222 int ret;
223
224 do {
225 ret = write(fd, from, len);
226 } while (ret < 0 && errno == EINTR);
227
228 return ret;
229}
230
231static void
232fd_setnonblock(int fd)
233{
234 int ret, flags;
235
236 do {
237 flags = fcntl(fd, F_GETFD);
238 } while (flags < 0 && errno == EINTR);
239
240 if (flags < 0) {
241 fatal( "%s: could not get flags for fd %d: %s",
242 __FUNCTION__, fd, strerror(errno) );
243 }
244
245 do {
246 ret = fcntl(fd, F_SETFD, flags | O_NONBLOCK);
247 } while (ret < 0 && errno == EINTR);
248
249 if (ret < 0) {
250 fatal( "%s: could not set fd %d to non-blocking: %s",
251 __FUNCTION__, fd, strerror(errno) );
252 }
253}
254
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700255
256static int
257fd_accept(int fd)
258{
259 struct sockaddr from;
260 socklen_t fromlen = sizeof(from);
261 int ret;
262
263 do {
264 ret = accept(fd, &from, &fromlen);
265 } while (ret < 0 && errno == EINTR);
266
267 return ret;
268}
269
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800270/** FD EVENT LOOP
271 **/
272
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700273/* A Looper object is used to monitor activity on one or more
274 * file descriptors (e.g sockets).
275 *
276 * - call looper_add() to register a function that will be
277 * called when events happen on the file descriptor.
278 *
279 * - call looper_enable() or looper_disable() to enable/disable
280 * the set of monitored events for a given file descriptor.
281 *
282 * - call looper_del() to unregister a file descriptor.
283 * this does *not* close the file descriptor.
284 *
285 * Note that you can only provide a single function to handle
286 * all events related to a given file descriptor.
287
288 * You can call looper_enable/_disable/_del within a function
289 * callback.
290 */
291
292/* the current implementation uses Linux's epoll facility
293 * the event mask we use are simply combinations of EPOLLIN
294 * EPOLLOUT, EPOLLHUP and EPOLLERR
295 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800296#include <sys/epoll.h>
297
298#define MAX_CHANNELS 16
299#define MAX_EVENTS (MAX_CHANNELS+1) /* each channel + the serial fd */
300
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700301/* the event handler function type, 'user' is a user-specific
302 * opaque pointer passed to looper_add().
303 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800304typedef void (*EventFunc)( void* user, int events );
305
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700306/* bit flags for the LoopHook structure.
307 *
308 * HOOK_PENDING means that an event happened on the
309 * corresponding file descriptor.
310 *
311 * HOOK_CLOSING is used to delay-close monitored
312 * file descriptors.
313 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800314enum {
315 HOOK_PENDING = (1 << 0),
316 HOOK_CLOSING = (1 << 1),
317};
318
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700319/* A LoopHook structure is used to monitor a given
320 * file descriptor and record its event handler.
321 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800322typedef struct {
323 int fd;
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700324 int wanted; /* events we are monitoring */
325 int events; /* events that occured */
326 int state; /* see HOOK_XXX constants */
327 void* ev_user; /* user-provided handler parameter */
328 EventFunc ev_func; /* event handler callback */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800329} LoopHook;
330
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700331/* Looper is the main object modeling a looper object
332 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800333typedef struct {
334 int epoll_fd;
335 int num_fds;
336 int max_fds;
337 struct epoll_event* events;
338 LoopHook* hooks;
339} Looper;
340
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700341/* initialize a looper object */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800342static void
343looper_init( Looper* l )
344{
345 l->epoll_fd = epoll_create(4);
346 l->num_fds = 0;
347 l->max_fds = 0;
348 l->events = NULL;
349 l->hooks = NULL;
350}
351
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700352/* finalize a looper object */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800353static void
354looper_done( Looper* l )
355{
356 xfree(l->events);
357 xfree(l->hooks);
358 l->max_fds = 0;
359 l->num_fds = 0;
360
361 close(l->epoll_fd);
362 l->epoll_fd = -1;
363}
364
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700365/* return the LoopHook corresponding to a given
366 * monitored file descriptor, or NULL if not found
367 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800368static LoopHook*
369looper_find( Looper* l, int fd )
370{
371 LoopHook* hook = l->hooks;
372 LoopHook* end = hook + l->num_fds;
373
374 for ( ; hook < end; hook++ ) {
375 if (hook->fd == fd)
376 return hook;
377 }
378 return NULL;
379}
380
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700381/* grow the arrays in the looper object */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800382static void
383looper_grow( Looper* l )
384{
385 int old_max = l->max_fds;
386 int new_max = old_max + (old_max >> 1) + 4;
387 int n;
388
389 xrenew( l->events, new_max );
390 xrenew( l->hooks, new_max );
391 l->max_fds = new_max;
392
393 /* now change the handles to all events */
394 for (n = 0; n < l->num_fds; n++) {
395 struct epoll_event ev;
396 LoopHook* hook = l->hooks + n;
397
398 ev.events = hook->wanted;
399 ev.data.ptr = hook;
400 epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, hook->fd, &ev );
401 }
402}
403
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700404/* register a file descriptor and its event handler.
405 * no event mask will be enabled
406 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800407static void
408looper_add( Looper* l, int fd, EventFunc func, void* user )
409{
410 struct epoll_event ev;
411 LoopHook* hook;
412
413 if (l->num_fds >= l->max_fds)
414 looper_grow(l);
415
416 hook = l->hooks + l->num_fds;
417
418 hook->fd = fd;
419 hook->ev_user = user;
420 hook->ev_func = func;
421 hook->state = 0;
422 hook->wanted = 0;
423 hook->events = 0;
424
425 fd_setnonblock(fd);
426
427 ev.events = 0;
428 ev.data.ptr = hook;
429 epoll_ctl( l->epoll_fd, EPOLL_CTL_ADD, fd, &ev );
430
431 l->num_fds += 1;
432}
433
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700434/* unregister a file descriptor and its event handler
435 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800436static void
437looper_del( Looper* l, int fd )
438{
439 LoopHook* hook = looper_find( l, fd );
440
441 if (!hook) {
442 D( "%s: invalid fd: %d", __FUNCTION__, fd );
443 return;
444 }
445 /* don't remove the hook yet */
446 hook->state |= HOOK_CLOSING;
447
448 epoll_ctl( l->epoll_fd, EPOLL_CTL_DEL, fd, NULL );
449}
450
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700451/* enable monitoring of certain events for a file
452 * descriptor. This adds 'events' to the current
453 * event mask
454 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800455static void
456looper_enable( Looper* l, int fd, int events )
457{
458 LoopHook* hook = looper_find( l, fd );
459
460 if (!hook) {
461 D("%s: invalid fd: %d", __FUNCTION__, fd );
462 return;
463 }
464
465 if (events & ~hook->wanted) {
466 struct epoll_event ev;
467
468 hook->wanted |= events;
469 ev.events = hook->wanted;
470 ev.data.ptr = hook;
471
472 epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, fd, &ev );
473 }
474}
475
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700476/* disable monitoring of certain events for a file
477 * descriptor. This ignores events that are not
478 * currently enabled.
479 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800480static void
481looper_disable( Looper* l, int fd, int events )
482{
483 LoopHook* hook = looper_find( l, fd );
484
485 if (!hook) {
486 D("%s: invalid fd: %d", __FUNCTION__, fd );
487 return;
488 }
489
490 if (events & hook->wanted) {
491 struct epoll_event ev;
492
493 hook->wanted &= ~events;
494 ev.events = hook->wanted;
495 ev.data.ptr = hook;
496
497 epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, fd, &ev );
498 }
499}
500
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700501/* wait until an event occurs on one of the registered file
502 * descriptors. Only returns in case of error !!
503 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800504static void
505looper_loop( Looper* l )
506{
507 for (;;) {
508 int n, count;
509
510 do {
511 count = epoll_wait( l->epoll_fd, l->events, l->num_fds, -1 );
512 } while (count < 0 && errno == EINTR);
513
514 if (count < 0) {
515 D("%s: error: %s", __FUNCTION__, strerror(errno) );
516 return;
517 }
518
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700519 if (count == 0) {
520 D("%s: huh ? epoll returned count=0", __FUNCTION__);
521 continue;
522 }
523
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800524 /* mark all pending hooks */
525 for (n = 0; n < count; n++) {
526 LoopHook* hook = l->events[n].data.ptr;
527 hook->state = HOOK_PENDING;
528 hook->events = l->events[n].events;
529 }
530
531 /* execute hook callbacks. this may change the 'hooks'
532 * and 'events' array, as well as l->num_fds, so be careful */
533 for (n = 0; n < l->num_fds; n++) {
534 LoopHook* hook = l->hooks + n;
535 if (hook->state & HOOK_PENDING) {
536 hook->state &= ~HOOK_PENDING;
537 hook->ev_func( hook->ev_user, hook->events );
538 }
539 }
540
541 /* now remove all the hooks that were closed by
542 * the callbacks */
543 for (n = 0; n < l->num_fds;) {
544 LoopHook* hook = l->hooks + n;
545
546 if (!(hook->state & HOOK_CLOSING)) {
547 n++;
548 continue;
549 }
550
551 hook[0] = l->hooks[l->num_fds-1];
552 l->num_fds -= 1;
553 }
554 }
555}
556
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700557#if T_ACTIVE
558char*
559quote( const void* data, int len )
560{
561 const char* p = data;
562 const char* end = p + len;
563 int count = 0;
564 int phase = 0;
565 static char* buff = NULL;
566
567 for (phase = 0; phase < 2; phase++) {
568 if (phase != 0) {
569 xfree(buff);
570 buff = xalloc(count+1);
571 }
572 count = 0;
573 for (p = data; p < end; p++) {
574 int c = *p;
575
576 if (c == '\\') {
577 if (phase != 0) {
578 buff[count] = buff[count+1] = '\\';
579 }
580 count += 2;
581 continue;
582 }
583
584 if (c >= 32 && c < 127) {
585 if (phase != 0)
586 buff[count] = c;
587 count += 1;
588 continue;
589 }
590
591
592 if (c == '\t') {
593 if (phase != 0) {
594 memcpy(buff+count, "<TAB>", 5);
595 }
596 count += 5;
597 continue;
598 }
599 if (c == '\n') {
600 if (phase != 0) {
601 memcpy(buff+count, "<LN>", 4);
602 }
603 count += 4;
604 continue;
605 }
606 if (c == '\r') {
607 if (phase != 0) {
608 memcpy(buff+count, "<CR>", 4);
609 }
610 count += 4;
611 continue;
612 }
613
614 if (phase != 0) {
615 buff[count+0] = '\\';
616 buff[count+1] = 'x';
617 buff[count+2] = "0123456789abcdef"[(c >> 4) & 15];
618 buff[count+3] = "0123456789abcdef"[ (c) & 15];
619 }
620 count += 4;
621 }
622 }
623 buff[count] = 0;
624 return buff;
625}
626#endif /* T_ACTIVE */
627
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800628/** PACKETS
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700629 **
630 ** We need a way to buffer data before it can be sent to the
631 ** corresponding file descriptor. We use linked list of Packet
632 ** objects to do this.
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800633 **/
634
635typedef struct Packet Packet;
636
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700637#define MAX_PAYLOAD 4000
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800638
639struct Packet {
640 Packet* next;
641 int len;
642 int channel;
643 uint8_t data[ MAX_PAYLOAD ];
644};
645
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700646/* we expect to alloc/free a lot of packets during
647 * operations so use a single linked list of free packets
648 * to keep things speedy and simple.
649 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800650static Packet* _free_packets;
651
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700652/* Allocate a packet */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800653static Packet*
654packet_alloc(void)
655{
656 Packet* p = _free_packets;
657 if (p != NULL) {
658 _free_packets = p->next;
659 } else {
660 xnew(p);
661 }
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700662 p->next = NULL;
663 p->len = 0;
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800664 p->channel = -1;
665 return p;
666}
667
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700668/* Release a packet. This takes the address of a packet
669 * pointer that will be set to NULL on exit (avoids
670 * referencing dangling pointers in case of bugs)
671 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800672static void
673packet_free( Packet* *ppacket )
674{
675 Packet* p = *ppacket;
676 if (p) {
677 p->next = _free_packets;
678 _free_packets = p;
679 *ppacket = NULL;
680 }
681}
682
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800683/** PACKET RECEIVER
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700684 **
685 ** Simple abstraction for something that can receive a packet
686 ** from a FDHandler (see below) or something else.
687 **
688 ** Send a packet to it with 'receiver_post'
689 **
690 ** Call 'receiver_close' to indicate that the corresponding
691 ** packet source was closed.
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800692 **/
693
694typedef void (*PostFunc) ( void* user, Packet* p );
695typedef void (*CloseFunc)( void* user );
696
697typedef struct {
698 PostFunc post;
699 CloseFunc close;
700 void* user;
701} Receiver;
702
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700703/* post a packet to a receiver. Note that this transfers
704 * ownership of the packet to the receiver.
705 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800706static __inline__ void
707receiver_post( Receiver* r, Packet* p )
708{
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700709 if (r->post)
710 r->post( r->user, p );
711 else
712 packet_free(&p);
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800713}
714
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700715/* tell a receiver the packet source was closed.
716 * this will also prevent further posting to the
717 * receiver.
718 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800719static __inline__ void
720receiver_close( Receiver* r )
721{
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700722 if (r->close) {
723 r->close( r->user );
724 r->close = NULL;
725 }
726 r->post = NULL;
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800727}
728
729
730/** FD HANDLERS
731 **
732 ** these are smart listeners that send incoming packets to a receiver
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700733 ** and can queue one or more outgoing packets and send them when
734 ** possible to the FD.
735 **
736 ** note that we support clean shutdown of file descriptors,
737 ** i.e. we try to send all outgoing packets before destroying
738 ** the FDHandler.
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800739 **/
740
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700741typedef struct FDHandler FDHandler;
742typedef struct FDHandlerList FDHandlerList;
743
744struct FDHandler {
745 int fd;
746 FDHandlerList* list;
747 char closing;
748 Receiver receiver[1];
749
750 /* queue of outgoing packets */
751 int out_pos;
752 Packet* out_first;
753 Packet** out_ptail;
754
755 FDHandler* next;
756 FDHandler** pref;
757
758};
759
760struct FDHandlerList {
761 /* the looper that manages the fds */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800762 Looper* looper;
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800763
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700764 /* list of active FDHandler objects */
765 FDHandler* active;
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800766
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700767 /* list of closing FDHandler objects.
768 * these are waiting to push their
769 * queued packets to the fd before
770 * freeing themselves.
771 */
772 FDHandler* closing;
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800773
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700774};
775
776/* remove a FDHandler from its current list */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800777static void
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700778fdhandler_remove( FDHandler* f )
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800779{
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700780 f->pref[0] = f->next;
781 if (f->next)
782 f->next->pref = f->pref;
783}
784
785/* add a FDHandler to a given list */
786static void
787fdhandler_prepend( FDHandler* f, FDHandler** list )
788{
789 f->next = list[0];
790 f->pref = list;
791 list[0] = f;
792 if (f->next)
793 f->next->pref = &f->next;
794}
795
796/* initialize a FDHandler list */
797static void
798fdhandler_list_init( FDHandlerList* list, Looper* looper )
799{
800 list->looper = looper;
801 list->active = NULL;
802 list->closing = NULL;
803}
804
805
806/* close a FDHandler (and free it). Note that this will not
807 * perform a graceful shutdown, i.e. all packets in the
808 * outgoing queue will be immediately free.
809 *
810 * this *will* notify the receiver that the file descriptor
811 * was closed.
812 *
813 * you should call fdhandler_shutdown() if you want to
814 * notify the FDHandler that its packet source is closed.
815 */
816static void
817fdhandler_close( FDHandler* f )
818{
819 /* notify receiver */
820 receiver_close(f->receiver);
821
822 /* remove the handler from its list */
823 fdhandler_remove(f);
824
825 /* get rid of outgoing packet queue */
826 if (f->out_first != NULL) {
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800827 Packet* p;
828 while ((p = f->out_first) != NULL) {
829 f->out_first = p->next;
830 packet_free(&p);
831 }
832 }
833
834 /* get rid of file descriptor */
835 if (f->fd >= 0) {
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700836 looper_del( f->list->looper, f->fd );
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800837 close(f->fd);
838 f->fd = -1;
839 }
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700840
841 f->list = NULL;
842 xfree(f);
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800843}
844
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700845/* Ask the FDHandler to cleanly shutdown the connection,
846 * i.e. send any pending outgoing packets then auto-free
847 * itself.
848 */
849static void
850fdhandler_shutdown( FDHandler* f )
851{
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800852
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700853 if (f->out_first != NULL && !f->closing)
854 {
855 /* move the handler to the 'closing' list */
856 f->closing = 1;
857 fdhandler_remove(f);
858 fdhandler_prepend(f, &f->list->closing);
859
860 /* notify the receiver that we're closing */
861 receiver_close(f->receiver);
862 return;
863 }
864
865 fdhandler_close(f);
866}
867
868/* Enqueue a new packet that the FDHandler will
869 * send through its file descriptor.
870 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800871static void
872fdhandler_enqueue( FDHandler* f, Packet* p )
873{
874 Packet* first = f->out_first;
875
876 p->next = NULL;
877 f->out_ptail[0] = p;
878 f->out_ptail = &p->next;
879
880 if (first == NULL) {
881 f->out_pos = 0;
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700882 looper_enable( f->list->looper, f->fd, EPOLLOUT );
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800883 }
884}
885
886
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700887/* FDHandler file descriptor event callback for read/write ops */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800888static void
889fdhandler_event( FDHandler* f, int events )
890{
891 int len;
892
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700893 /* in certain cases, it's possible to have both EPOLLIN and
894 * EPOLLHUP at the same time. This indicates that there is incoming
895 * data to read, but that the connection was nonetheless closed
896 * by the sender. Be sure to read the data before closing
897 * the receiver to avoid packet loss.
898 */
899
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800900 if (events & EPOLLIN) {
901 Packet* p = packet_alloc();
902 int len;
903
904 if ((len = fd_read(f->fd, p->data, MAX_PAYLOAD)) < 0) {
905 D("%s: can't recv: %s", __FUNCTION__, strerror(errno));
906 packet_free(&p);
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700907 } else if (len > 0) {
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800908 p->len = len;
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700909 p->channel = -101; /* special debug value, not used */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800910 receiver_post( f->receiver, p );
911 }
912 }
913
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800914 if (events & (EPOLLHUP|EPOLLERR)) {
915 /* disconnection */
916 D("%s: disconnect on fd %d", __FUNCTION__, f->fd);
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700917 fdhandler_close(f);
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800918 return;
919 }
920
921 if (events & EPOLLOUT && f->out_first) {
922 Packet* p = f->out_first;
923 int avail, len;
924
925 avail = p->len - f->out_pos;
926 if ((len = fd_write(f->fd, p->data + f->out_pos, avail)) < 0) {
927 D("%s: can't send: %s", __FUNCTION__, strerror(errno));
928 } else {
929 f->out_pos += len;
930 if (f->out_pos >= p->len) {
931 f->out_pos = 0;
932 f->out_first = p->next;
933 packet_free(&p);
934 if (f->out_first == NULL) {
935 f->out_ptail = &f->out_first;
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700936 looper_disable( f->list->looper, f->fd, EPOLLOUT );
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800937 }
938 }
939 }
940 }
941}
942
943
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700944/* Create a new FDHandler that monitors read/writes */
945static FDHandler*
946fdhandler_new( int fd,
947 FDHandlerList* list,
948 Receiver* receiver )
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800949{
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700950 FDHandler* f = xalloc0(sizeof(*f));
951
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800952 f->fd = fd;
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700953 f->list = list;
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800954 f->receiver[0] = receiver[0];
955 f->out_first = NULL;
956 f->out_ptail = &f->out_first;
957 f->out_pos = 0;
958
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700959 fdhandler_prepend(f, &list->active);
960
961 looper_add( list->looper, fd, (EventFunc) fdhandler_event, f );
962 looper_enable( list->looper, fd, EPOLLIN );
963
964 return f;
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800965}
966
967
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700968/* event callback function to monitor accepts() on server sockets.
969 * the convention used here is that the receiver will receive a
970 * dummy packet with the new client socket in p->channel
971 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800972static void
973fdhandler_accept_event( FDHandler* f, int events )
974{
975 if (events & EPOLLIN) {
976 /* this is an accept - send a dummy packet to the receiver */
977 Packet* p = packet_alloc();
978
979 D("%s: accepting on fd %d", __FUNCTION__, f->fd);
980 p->data[0] = 1;
981 p->len = 1;
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700982 p->channel = fd_accept(f->fd);
983 if (p->channel < 0) {
984 D("%s: accept failed ?: %s", __FUNCTION__, strerror(errno));
985 packet_free(&p);
986 return;
987 }
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800988 receiver_post( f->receiver, p );
989 }
990
991 if (events & (EPOLLHUP|EPOLLERR)) {
992 /* disconnecting !! */
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700993 D("%s: closing accept fd %d", __FUNCTION__, f->fd);
994 fdhandler_close(f);
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800995 return;
996 }
997}
998
999
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001000/* Create a new FDHandler used to monitor new connections on a
1001 * server socket. The receiver must expect the new connection
1002 * fd in the 'channel' field of a dummy packet.
1003 */
1004static FDHandler*
1005fdhandler_new_accept( int fd,
1006 FDHandlerList* list,
1007 Receiver* receiver )
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001008{
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001009 FDHandler* f = xalloc0(sizeof(*f));
1010
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001011 f->fd = fd;
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001012 f->list = list;
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001013 f->receiver[0] = receiver[0];
1014
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001015 fdhandler_prepend(f, &list->active);
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001016
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001017 looper_add( list->looper, fd, (EventFunc) fdhandler_accept_event, f );
1018 looper_enable( list->looper, fd, EPOLLIN );
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001019 listen( fd, 5 );
1020
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001021 return f;
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001022}
1023
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001024/** SERIAL CONNECTION STATE
1025 **
1026 ** The following is used to handle the framing protocol
1027 ** used on the serial port connection.
1028 **/
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001029
1030/* each packet is made of a 6 byte header followed by a payload
1031 * the header looks like:
1032 *
1033 * offset size description
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001034 * 0 2 a 2-byte hex string for the channel number
1035 * 4 4 a 4-char hex string for the size of the payload
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001036 * 6 n the payload itself
1037 */
1038#define HEADER_SIZE 6
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001039#define CHANNEL_OFFSET 0
1040#define LENGTH_OFFSET 2
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001041#define CHANNEL_SIZE 2
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001042#define LENGTH_SIZE 4
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001043
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001044#define CHANNEL_CONTROL 0
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001045
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001046/* The Serial object receives data from the serial port,
1047 * extracts the payload size and channel index, then sends
1048 * the resulting messages as a packet to a generic receiver.
1049 *
1050 * You can also use serial_send to send a packet through
1051 * the serial port.
1052 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001053typedef struct Serial {
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001054 FDHandler* fdhandler; /* used to monitor serial port fd */
1055 Receiver receiver[1]; /* send payload there */
1056 int in_len; /* current bytes in input packet */
1057 int in_datalen; /* payload size, or 0 when reading header */
1058 int in_channel; /* extracted channel number */
1059 Packet* in_packet; /* used to read incoming packets */
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001060} Serial;
1061
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001062
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001063/* a callback called when the serial port's fd is closed */
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001064static void
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001065serial_fd_close( Serial* s )
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001066{
1067 fatal("unexpected serial port close !!");
1068}
1069
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001070static void
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001071serial_dump( Packet* p, const char* funcname )
1072{
1073 T("%s: %03d bytes: '%s'",
1074 funcname, p->len, quote(p->data, p->len));
1075}
1076
1077/* a callback called when a packet arrives from the serial port's FDHandler.
1078 *
1079 * This will essentially parse the header, extract the channel number and
1080 * the payload size and store them in 'in_datalen' and 'in_channel'.
1081 *
1082 * After that, the payload is sent to the receiver once completed.
1083 */
1084static void
1085serial_fd_receive( Serial* s, Packet* p )
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001086{
1087 int rpos = 0, rcount = p->len;
1088 Packet* inp = s->in_packet;
1089 int inpos = s->in_len;
1090
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001091 serial_dump( p, __FUNCTION__ );
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001092
1093 while (rpos < rcount)
1094 {
1095 int avail = rcount - rpos;
1096
1097 /* first, try to read the header */
1098 if (s->in_datalen == 0) {
1099 int wanted = HEADER_SIZE - inpos;
1100 if (avail > wanted)
1101 avail = wanted;
1102
1103 memcpy( inp->data + inpos, p->data + rpos, avail );
1104 inpos += avail;
1105 rpos += avail;
1106
1107 if (inpos == HEADER_SIZE) {
1108 s->in_datalen = hex2int( inp->data + LENGTH_OFFSET, LENGTH_SIZE );
1109 s->in_channel = hex2int( inp->data + CHANNEL_OFFSET, CHANNEL_SIZE );
1110
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001111 if (s->in_datalen <= 0) {
1112 D("ignoring %s packet from serial port",
1113 s->in_datalen ? "empty" : "malformed");
1114 s->in_datalen = 0;
1115 }
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001116
1117 //D("received %d bytes packet for channel %d", s->in_datalen, s->in_channel);
1118 inpos = 0;
1119 }
1120 }
1121 else /* then, populate the packet itself */
1122 {
1123 int wanted = s->in_datalen - inpos;
1124
1125 if (avail > wanted)
1126 avail = wanted;
1127
1128 memcpy( inp->data + inpos, p->data + rpos, avail );
1129 inpos += avail;
1130 rpos += avail;
1131
1132 if (inpos == s->in_datalen) {
1133 if (s->in_channel < 0) {
1134 D("ignoring %d bytes addressed to channel %d",
1135 inpos, s->in_channel);
1136 } else {
1137 inp->len = inpos;
1138 inp->channel = s->in_channel;
1139 receiver_post( s->receiver, inp );
1140 s->in_packet = inp = packet_alloc();
1141 }
1142 s->in_datalen = 0;
1143 inpos = 0;
1144 }
1145 }
1146 }
1147 s->in_len = inpos;
1148 packet_free(&p);
1149}
1150
1151
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001152/* send a packet to the serial port.
1153 * this assumes that p->len and p->channel contain the payload's
1154 * size and channel and will add the appropriate header.
1155 */
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001156static void
1157serial_send( Serial* s, Packet* p )
1158{
1159 Packet* h = packet_alloc();
1160
1161 //D("sending to serial %d bytes from channel %d: '%.*s'", p->len, p->channel, p->len, p->data);
1162
1163 /* insert a small header before this packet */
1164 h->len = HEADER_SIZE;
1165 int2hex( p->len, h->data + LENGTH_OFFSET, LENGTH_SIZE );
1166 int2hex( p->channel, h->data + CHANNEL_OFFSET, CHANNEL_SIZE );
1167
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001168 serial_dump( h, __FUNCTION__ );
1169 serial_dump( p, __FUNCTION__ );
1170
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001171 fdhandler_enqueue( s->fdhandler, h );
1172 fdhandler_enqueue( s->fdhandler, p );
1173}
1174
1175
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001176/* initialize serial reader */
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001177static void
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001178serial_init( Serial* s,
1179 int fd,
1180 FDHandlerList* list,
1181 Receiver* receiver )
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001182{
1183 Receiver recv;
1184
1185 recv.user = s;
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001186 recv.post = (PostFunc) serial_fd_receive;
1187 recv.close = (CloseFunc) serial_fd_close;
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001188
1189 s->receiver[0] = receiver[0];
1190
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001191 s->fdhandler = fdhandler_new( fd, list, &recv );
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001192 s->in_len = 0;
1193 s->in_datalen = 0;
1194 s->in_channel = 0;
1195 s->in_packet = packet_alloc();
1196}
1197
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001198
1199/** CLIENTS
1200 **/
1201
1202typedef struct Client Client;
1203typedef struct Multiplexer Multiplexer;
1204
1205/* A Client object models a single qemud client socket
1206 * connection in the emulated system.
1207 *
1208 * the client first sends the name of the system service
1209 * it wants to contact (no framing), then waits for a 2
1210 * byte answer from qemud.
1211 *
1212 * the answer is either "OK" or "KO" to indicate
1213 * success or failure.
1214 *
1215 * In case of success, the client can send messages
1216 * to the service.
1217 *
1218 * In case of failure, it can disconnect or try sending
1219 * the name of another service.
1220 */
1221struct Client {
1222 Client* next;
1223 Client** pref;
1224 int channel;
1225 char registered;
1226 FDHandler* fdhandler;
1227 Multiplexer* multiplexer;
1228};
1229
1230struct Multiplexer {
1231 Client* clients;
1232 int last_channel;
1233 Serial serial[1];
1234 Looper looper[1];
1235 FDHandlerList fdhandlers[1];
1236};
1237
1238
1239static int multiplexer_open_channel( Multiplexer* mult, Packet* p );
1240static void multiplexer_close_channel( Multiplexer* mult, int channel );
1241static void multiplexer_serial_send( Multiplexer* mult, int channel, Packet* p );
1242
1243static void
1244client_dump( Client* c, Packet* p, const char* funcname )
1245{
1246 T("%s: client %p (%d): %3d bytes: '%s'",
1247 funcname, c, c->fdhandler->fd,
1248 p->len, quote(p->data, p->len));
1249}
1250
1251/* destroy a client */
1252static void
1253client_free( Client* c )
1254{
1255 /* remove from list */
1256 c->pref[0] = c->next;
1257 if (c->next)
1258 c->next->pref = c->pref;
1259
1260 c->channel = -1;
1261 c->registered = 0;
1262
1263 /* gently ask the FDHandler to shutdown to
1264 * avoid losing queued outgoing packets */
1265 if (c->fdhandler != NULL) {
1266 fdhandler_shutdown(c->fdhandler);
1267 c->fdhandler = NULL;
1268 }
1269
1270 xfree(c);
1271}
1272
1273
1274/* a function called when a client socket receives data */
1275static void
1276client_fd_receive( Client* c, Packet* p )
1277{
1278 client_dump(c, p, __FUNCTION__);
1279
1280 if (c->registered) {
1281 /* the client is registered, just send the
1282 * data through the serial port
1283 */
1284 multiplexer_serial_send(c->multiplexer, c->channel, p);
1285 return;
1286 }
1287
1288 if (c->channel > 0) {
1289 /* the client is waiting registration results.
1290 * this should not happen because the client
1291 * should wait for our 'ok' or 'ko'.
1292 * close the connection.
1293 */
1294 D("%s: bad client sending data before end of registration",
1295 __FUNCTION__);
1296 BAD_CLIENT:
1297 packet_free(&p);
1298 client_free(c);
1299 return;
1300 }
1301
1302 /* the client hasn't registered a service yet,
1303 * so this must be the name of a service, call
1304 * the multiplexer to start registration for
1305 * it.
1306 */
1307 D("%s: attempting registration for service '%.*s'",
1308 __FUNCTION__, p->len, p->data);
1309 c->channel = multiplexer_open_channel(c->multiplexer, p);
1310 if (c->channel < 0) {
1311 D("%s: service name too long", __FUNCTION__);
1312 goto BAD_CLIENT;
1313 }
1314 D("%s: -> received channel id %d", __FUNCTION__, c->channel);
1315 packet_free(&p);
1316}
1317
1318
1319/* a function called when the client socket is closed. */
1320static void
1321client_fd_close( Client* c )
1322{
1323 T("%s: client %p (%d)", __FUNCTION__, c, c->fdhandler->fd);
1324
1325 /* no need to shutdown the FDHandler */
1326 c->fdhandler = NULL;
1327
1328 /* tell the emulator we're out */
1329 if (c->channel > 0)
1330 multiplexer_close_channel(c->multiplexer, c->channel);
1331
1332 /* free the client */
1333 client_free(c);
1334}
1335
1336/* a function called when the multiplexer received a registration
1337 * response from the emulator for a given client.
1338 */
1339static void
1340client_registration( Client* c, int registered )
1341{
1342 Packet* p = packet_alloc();
1343
1344 /* sends registration status to client */
1345 if (!registered) {
1346 D("%s: registration failed for client %d", __FUNCTION__, c->channel);
1347 memcpy( p->data, "KO", 2 );
1348 p->len = 2;
1349 } else {
1350 D("%s: registration succeeded for client %d", __FUNCTION__, c->channel);
1351 memcpy( p->data, "OK", 2 );
1352 p->len = 2;
1353 }
1354 client_dump(c, p, __FUNCTION__);
1355 fdhandler_enqueue(c->fdhandler, p);
1356
1357 /* now save registration state
1358 */
1359 c->registered = registered;
1360 if (!registered) {
1361 /* allow the client to try registering another service */
1362 c->channel = -1;
1363 }
1364}
1365
1366/* send data to a client */
1367static void
1368client_send( Client* c, Packet* p )
1369{
1370 client_dump(c, p, __FUNCTION__);
1371 fdhandler_enqueue(c->fdhandler, p);
1372}
1373
1374
1375/* Create new client socket handler */
1376static Client*
1377client_new( Multiplexer* mult,
1378 int fd,
1379 FDHandlerList* pfdhandlers,
1380 Client** pclients )
1381{
1382 Client* c;
1383 Receiver recv;
1384
1385 xnew(c);
1386
1387 c->multiplexer = mult;
1388 c->next = NULL;
1389 c->pref = &c->next;
1390 c->channel = -1;
1391 c->registered = 0;
1392
1393 recv.user = c;
1394 recv.post = (PostFunc) client_fd_receive;
1395 recv.close = (CloseFunc) client_fd_close;
1396
1397 c->fdhandler = fdhandler_new( fd, pfdhandlers, &recv );
1398
1399 /* add to client list */
1400 c->next = *pclients;
1401 c->pref = pclients;
1402 *pclients = c;
1403 if (c->next)
1404 c->next->pref = &c->next;
1405
1406 return c;
1407}
1408
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001409/** GLOBAL MULTIPLEXER
1410 **/
1411
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001412/* find a client by its channel */
1413static Client*
1414multiplexer_find_client( Multiplexer* mult, int channel )
1415{
1416 Client* c = mult->clients;
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001417
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001418 for ( ; c != NULL; c = c->next ) {
1419 if (c->channel == channel)
1420 return c;
1421 }
1422 return NULL;
1423}
1424
1425/* handle control messages coming from the serial port
1426 * on CONTROL_CHANNEL.
1427 */
1428static void
1429multiplexer_handle_control( Multiplexer* mult, Packet* p )
1430{
1431 /* connection registration success */
1432 if (p->len == 15 && !memcmp(p->data, "ok:connect:", 11)) {
1433 int channel = hex2int(p->data+11, 4);
1434 Client* client = multiplexer_find_client(mult, channel);
1435
1436 /* note that 'client' can be NULL if the corresponding
1437 * socket was closed before the emulator response arrived.
1438 */
1439 if (client != NULL) {
1440 client_registration(client, 1);
1441 }
1442 goto EXIT;
1443 }
1444
1445 /* connection registration failure */
1446 if (p->len >= 15 && !memcmp(p->data, "ko:connect:",11)) {
1447 int channel = hex2int(p->data+11, 4);
1448 Client* client = multiplexer_find_client(mult, channel);
1449
1450 if (client != NULL)
1451 client_registration(client, 0);
1452
1453 goto EXIT;
1454 }
1455
1456 /* emulator-induced client disconnection */
1457 if (p->len == 15 && !memcmp(p->data, "disconnect:",11)) {
1458 int channel = hex2int(p->data+11, 4);
1459 Client* client = multiplexer_find_client(mult, channel);
1460
1461 if (client != NULL)
1462 client_free(client);
1463
1464 goto EXIT;
1465 }
1466
1467 D("%s: unknown control message: '%.*s'",
1468 __FUNCTION__, p->len, p->data);
1469
1470EXIT:
1471 packet_free(&p);
1472}
1473
1474/* a function called when an incoming packet comes from the serial port */
1475static void
1476multiplexer_serial_receive( Multiplexer* mult, Packet* p )
1477{
1478 Client* client;
1479
1480 if (p->channel == CHANNEL_CONTROL) {
1481 multiplexer_handle_control(mult, p);
1482 return;
1483 }
1484
1485 client = multiplexer_find_client(mult, p->channel);
1486 if (client != NULL) {
1487 client_send(client, p);
1488 return;
1489 }
1490
1491 D("%s: discarding packet for unknown channel %d", __FUNCTION__, p->channel);
1492 packet_free(&p);
1493}
1494
1495/* a function called when the serial reader closes */
1496static void
1497multiplexer_serial_close( Multiplexer* mult )
1498{
1499 fatal("unexpected close of serial reader");
1500}
1501
1502/* a function called to send a packet to the serial port */
1503static void
1504multiplexer_serial_send( Multiplexer* mult, int channel, Packet* p )
1505{
1506 p->channel = channel;
1507 serial_send( mult->serial, p );
1508}
1509
1510
1511
1512/* a function used by a client to allocate a new channel id and
1513 * ask the emulator to open it. 'service' must be a packet containing
1514 * the name of the service in its payload.
1515 *
1516 * returns -1 if the service name is too long.
1517 *
1518 * notice that client_registration() will be called later when
1519 * the answer arrives.
1520 */
1521static int
1522multiplexer_open_channel( Multiplexer* mult, Packet* service )
1523{
1524 Packet* p = packet_alloc();
1525 int len, channel;
1526
1527 /* find a free channel number, assume we don't have many
1528 * clients here. */
1529 {
1530 Client* c;
1531 TRY_AGAIN:
1532 channel = (++mult->last_channel) & 0xff;
1533
1534 for (c = mult->clients; c != NULL; c = c->next)
1535 if (c->channel == channel)
1536 goto TRY_AGAIN;
1537 }
1538
1539 len = snprintf((char*)p->data, sizeof p->data, "connect:%.*s:%04x", service->len, service->data, channel);
1540 if (len >= (int)sizeof(p->data)) {
1541 D("%s: weird, service name too long (%d > %d)", __FUNCTION__, len, sizeof(p->data));
1542 packet_free(&p);
1543 return -1;
1544 }
1545 p->channel = CHANNEL_CONTROL;
1546 p->len = len;
1547
1548 serial_send(mult->serial, p);
1549 return channel;
1550}
1551
1552/* used to tell the emulator a channel was closed by a client */
1553static void
1554multiplexer_close_channel( Multiplexer* mult, int channel )
1555{
1556 Packet* p = packet_alloc();
1557 int len = snprintf((char*)p->data, sizeof(p->data), "disconnect:%04x", channel);
1558
1559 if (len > (int)sizeof(p->data)) {
1560 /* should not happen */
1561 return;
1562 }
1563
1564 p->channel = CHANNEL_CONTROL;
1565 p->len = len;
1566
1567 serial_send(mult->serial, p);
1568}
1569
1570/* this function is used when a new connection happens on the control
1571 * socket.
1572 */
1573static void
1574multiplexer_control_accept( Multiplexer* m, Packet* p )
1575{
1576 /* the file descriptor for the new socket connection is
1577 * in p->channel. See fdhandler_accept_event() */
1578 int fd = p->channel;
1579 Client* client = client_new( m, fd, m->fdhandlers, &m->clients );
1580
1581 D("created client %p listening on fd %d", client, fd);
1582
1583 /* free dummy packet */
1584 packet_free(&p);
1585}
1586
1587static void
1588multiplexer_control_close( Multiplexer* m )
1589{
1590 fatal("unexpected multiplexer control close");
1591}
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001592
1593static void
1594multiplexer_init( Multiplexer* m, const char* serial_dev )
1595{
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001596 int fd, control_fd;
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001597 Receiver recv;
1598
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001599 /* initialize looper and fdhandlers list */
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001600 looper_init( m->looper );
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001601 fdhandler_list_init( m->fdhandlers, m->looper );
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001602
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001603 /* open the serial port */
1604 do {
1605 fd = open(serial_dev, O_RDWR);
1606 } while (fd < 0 && errno == EINTR);
1607
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001608 if (fd < 0) {
1609 fatal( "%s: could not open '%s': %s", __FUNCTION__, serial_dev,
1610 strerror(errno) );
1611 }
1612 // disable echo on serial lines
1613 if ( !memcmp( serial_dev, "/dev/ttyS", 9 ) ) {
1614 struct termios ios;
1615 tcgetattr( fd, &ios );
1616 ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
1617 tcsetattr( fd, TCSANOW, &ios );
1618 }
1619
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001620 /* initialize the serial reader/writer */
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001621 recv.user = m;
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001622 recv.post = (PostFunc) multiplexer_serial_receive;
1623 recv.close = (CloseFunc) multiplexer_serial_close;
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001624
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001625 serial_init( m->serial, fd, m->fdhandlers, &recv );
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001626
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001627 /* open the qemud control socket */
1628 recv.user = m;
1629 recv.post = (PostFunc) multiplexer_control_accept;
1630 recv.close = (CloseFunc) multiplexer_control_close;
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001631
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001632 fd = android_get_control_socket(CONTROL_SOCKET_NAME);
1633 if (fd < 0) {
1634 fatal("couldn't get fd for control socket '%s'", CONTROL_SOCKET_NAME);
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001635 }
1636
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001637 fdhandler_new_accept( fd, m->fdhandlers, &recv );
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001638
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001639 /* initialize clients list */
1640 m->clients = NULL;
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001641}
1642
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001643/** MAIN LOOP
1644 **/
1645
1646static Multiplexer _multiplexer[1];
1647
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001648int main( void )
1649{
1650 Multiplexer* m = _multiplexer;
1651
1652 /* extract the name of our serial device from the kernel
1653 * boot options that are stored in /proc/cmdline
1654 */
1655#define KERNEL_OPTION "android.qemud="
1656
1657 {
1658 char buff[1024];
1659 int fd, len;
1660 char* p;
1661 char* q;
1662
1663 fd = open( "/proc/cmdline", O_RDONLY );
1664 if (fd < 0) {
1665 D("%s: can't open /proc/cmdline !!: %s", __FUNCTION__,
1666 strerror(errno));
1667 exit(1);
1668 }
1669
1670 len = fd_read( fd, buff, sizeof(buff)-1 );
1671 close(fd);
1672 if (len < 0) {
1673 D("%s: can't read /proc/cmdline: %s", __FUNCTION__,
1674 strerror(errno));
1675 exit(1);
1676 }
1677 buff[len] = 0;
1678
1679 p = strstr( buff, KERNEL_OPTION );
1680 if (p == NULL) {
1681 D("%s: can't find '%s' in /proc/cmdline",
1682 __FUNCTION__, KERNEL_OPTION );
1683 exit(1);
1684 }
1685
1686 p += sizeof(KERNEL_OPTION)-1; /* skip option */
1687 q = p;
1688 while ( *q && *q != ' ' && *q != '\t' )
1689 q += 1;
1690
1691 snprintf( buff, sizeof(buff), "/dev/%.*s", q-p, p );
1692
1693 multiplexer_init( m, buff );
1694 }
1695
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001696 D( "entering main loop");
1697 looper_loop( m->looper );
1698 D( "unexpected termination !!" );
1699 return 0;
1700}