18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
12cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/sockets.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sysdeps.h"
14a7fb77d6eca56e61e94f62e7deb4120b60b1e919David 'Digit' Turner#include "qemu-common.h"
157a78db75ad42aea283f5073f51891464104a9fc3David 'Digit' Turner#include "qemu/timer.h"
16e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner#include "sysemu/char.h"
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <winsock2.h>
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/socket.h>
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/select.h>
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/types.h>
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <netinet/in.h>
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <netinet/tcp.h>
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <netdb.h>
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
283e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner#define  DEBUG  0
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  D_ACTIVE  DEBUG
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DEBUG
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  D(...)  do { if (D_ACTIVE) fprintf(stderr, __VA_ARGS__); } while (0)
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  D(...)  ((void)0)
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** TIME
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSysTime
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_time_ms( void )
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
44dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** TIMERS
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct SysTimerRec_ {
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QEMUTimer*    timer;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QEMUTimerCB*  callback;
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void*         opaque;
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysTimer      next;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} SysTimerRec;
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  MAX_TIMERS  32
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SysTimerRec  _s_timers0[ MAX_TIMERS ];
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SysTimer     _s_free_timers;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_init_timers( void )
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < MAX_TIMERS-1; nn++)
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        _s_timers0[nn].next = _s_timers0 + (nn+1);
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    _s_free_timers = _s_timers0;
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SysTimer
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_timer_alloc( void )
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysTimer  timer = _s_free_timers;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (timer != NULL) {
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        _s_free_timers = timer->next;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        timer->next    = NULL;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        timer->timer   = NULL;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return timer;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_timer_free( SysTimer  timer )
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (timer->timer) {
90dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_del( timer->timer );
91dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_free( timer->timer );
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        timer->timer = NULL;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    timer->next    = _s_free_timers;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    _s_free_timers = timer;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSysTimer   sys_timer_create( void )
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysTimer  timer = sys_timer_alloc();
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return timer;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_timer_set( SysTimer  timer, SysTime  when, SysCallback   _callback, void*  opaque )
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QEMUTimerCB*  callback = (QEMUTimerCB*)_callback;
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (callback == NULL) {  /* unsetting the timer */
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (timer->timer) {
112dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            timer_del( timer->timer );
113dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            timer_free( timer->timer );
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            timer->timer = NULL;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        timer->callback = callback;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        timer->opaque   = NULL;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( timer->timer ) {
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if ( timer->callback == callback && timer->opaque == opaque )
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto ReuseTimer;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* need to replace the timer */
126dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner         timer_free( timer->timer );
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
129dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer->timer    = timer_new(QEMU_CLOCK_REALTIME, SCALE_MS, callback, opaque );
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    timer->callback = callback;
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    timer->opaque   = opaque;
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectReuseTimer:
134dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_mod( timer->timer, when );
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_timer_unset( SysTimer  timer )
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (timer->timer) {
141dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_del( timer->timer );
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_timer_destroy( SysTimer  timer )
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_timer_free( timer );
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** CHANNELS
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct SysChannelRec_ {
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                 fd;
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannelCallback  callback;
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void*               opaque;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel          next;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} SysChannelRec;
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  MAX_CHANNELS  16
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SysChannelRec  _s_channels0[ MAX_CHANNELS ];
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SysChannel     _s_free_channels;
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_init_channels( void )
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( nn = 0; nn < MAX_CHANNELS-1; nn++ ) {
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        _s_channels0[nn].next = _s_channels0 + (nn+1);
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    _s_free_channels = _s_channels0;
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SysChannel
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_alloc( )
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel  channel = _s_free_channels;
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (channel != NULL) {
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        _s_free_channels  = channel->next;
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        channel->next     = NULL;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        channel->fd       = -1;
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        channel->callback = NULL;
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        channel->opaque   = NULL;
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return channel;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_free( SysChannel  channel )
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (channel->fd >= 0) {
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close( channel->fd );
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        channel->fd = -1;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    channel->next    = _s_free_channels;
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    _s_free_channels = channel;
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_read_handler( void*  _channel )
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel  channel = _channel;
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D( "%s: read event for channel %p:%d\n", __FUNCTION__,
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       channel, channel->fd );
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    channel->callback( channel->opaque, SYS_EVENT_READ );
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_write_handler( void*  _channel )
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel  channel = _channel;
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D( "%s: write event for channel %p:%d\n", __FUNCTION__, channel, channel->fd );
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    channel->callback( channel->opaque, SYS_EVENT_WRITE );
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_on( SysChannel          channel,
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int                 events,
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                SysChannelCallback  event_callback,
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                void*               event_opaque )
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    IOHandler*  read_handler  = NULL;
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    IOHandler*  write_handler = NULL;
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (events & SYS_EVENT_READ) {
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        read_handler = sys_channel_read_handler;
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (events & SYS_EVENT_WRITE) {
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        write_handler = sys_channel_write_handler;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    channel->callback = event_callback;
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    channel->opaque   = event_opaque;
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( channel->fd, read_handler, write_handler, channel );
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_read( SysChannel  channel, void*  buffer, int  size )
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   len = size;
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char* buf = (char*) buffer;
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  ret = socket_recv(channel->fd, buf, len);
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0) {
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (errno == EINTR)
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                continue;
252ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner            if (errno == EWOULDBLOCK || errno == EAGAIN)
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            D( "%s: after reading %d bytes, recv() returned error %d: %s\n",
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                __FUNCTION__, size - len, errno, errno_str);
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (ret == 0) {
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buf += ret;
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len -= ret;
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return size - len;
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_write( SysChannel  channel, const void*  buffer, int  size )
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int         len = size;
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char* buf = (const char*) buffer;
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  ret = socket_send(channel->fd, buf, len);
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0) {
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (errno == EINTR)
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                continue;
279ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner            if (errno == EWOULDBLOCK || errno == EAGAIN)
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            D( "%s: send() returned error %d: %s\n",
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                __FUNCTION__, errno, errno_str);
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (ret == 0) {
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buf += ret;
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len -= ret;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return size - len;
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid  sys_channel_close( SysChannel  channel )
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( channel->fd, NULL, NULL, NULL );
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_channel_free( channel );
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid  sys_main_init( void )
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_init_channels();
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_init_timers();
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint   sys_main_loop( void )
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* no looping, qemu has its own event loop */
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSysChannel
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_create_tcp_server( int port )
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel  channel = sys_channel_alloc();
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    channel->fd = socket_anyaddr_server( port, SOCKET_STREAM );
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (channel->fd < 0) {
3235973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner        D( "%s: failed to created network socket on TCP:%d\n",
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            __FUNCTION__, port );
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sys_channel_free( channel );
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D( "%s: server channel %p:%d now listening on port %d\n",
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       __FUNCTION__, channel, channel->fd, port );
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return channel;
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSysChannel
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_create_tcp_handler( SysChannel  server_channel )
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel  channel = sys_channel_alloc();
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D( "%s: creating handler from server channel %p:%d\n", __FUNCTION__,
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       server_channel, server_channel->fd );
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    channel->fd = socket_accept_any( server_channel->fd );
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (channel->fd < 0) {
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror( "accept" );
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sys_channel_free( channel );
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* disable Nagle algorithm */
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nodelay( channel->fd );
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D( "%s: handler %p:%d created from server %p:%d\n", __FUNCTION__,
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        server_channel, server_channel->fd, channel, channel->fd );
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     return channel;
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSysChannel
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsys_channel_create_tcp_client( const char*  hostname, int  port )
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel  channel = sys_channel_alloc();
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    channel->fd = socket_network_client( hostname, port, SOCKET_STREAM );
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (channel->fd < 0) {
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sys_channel_free(channel);
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    };
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* set to non-blocking and disable Nagle algorithm */
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock( channel->fd );
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nodelay( channel->fd );
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return channel;
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
379