Home | History | Annotate | Download | only in telephony
      1 /* Copyright (C) 2007-2008 The Android Open Source Project
      2 **
      3 ** This software is licensed under the terms of the GNU General Public
      4 ** License version 2, as published by the Free Software Foundation, and
      5 ** may be copied, distributed, and modified under those terms.
      6 **
      7 ** This program is distributed in the hope that it will be useful,
      8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 ** GNU General Public License for more details.
     11 */
     12 #include "sockets.h"
     13 #include "sysdeps.h"
     14 #include "qemu-common.h"
     15 #include "qemu-timer.h"
     16 #include "qemu-char.h"
     17 #ifdef _WIN32
     18 #include <winsock2.h>
     19 #else
     20 #include <sys/socket.h>
     21 #include <sys/select.h>
     22 #include <sys/types.h>
     23 #include <netinet/in.h>
     24 #include <netinet/tcp.h>
     25 #include <netdb.h>
     26 #endif
     27 
     28 #define  DEBUG  0
     29 
     30 #define  D_ACTIVE  DEBUG
     31 
     32 #if DEBUG
     33 #define  D(...)  do { if (D_ACTIVE) fprintf(stderr, __VA_ARGS__); } while (0)
     34 #else
     35 #define  D(...)  ((void)0)
     36 #endif
     37 
     38 /** TIME
     39  **/
     40 
     41 SysTime
     42 sys_time_ms( void )
     43 {
     44     return qemu_get_clock_ms(rt_clock);
     45 }
     46 
     47 /** TIMERS
     48  **/
     49 
     50 typedef struct SysTimerRec_ {
     51     QEMUTimer*    timer;
     52     QEMUTimerCB*  callback;
     53     void*         opaque;
     54     SysTimer      next;
     55 } SysTimerRec;
     56 
     57 #define  MAX_TIMERS  32
     58 
     59 static SysTimerRec  _s_timers0[ MAX_TIMERS ];
     60 static SysTimer     _s_free_timers;
     61 
     62 static void
     63 sys_init_timers( void )
     64 {
     65     int  nn;
     66     for (nn = 0; nn < MAX_TIMERS-1; nn++)
     67         _s_timers0[nn].next = _s_timers0 + (nn+1);
     68 
     69     _s_free_timers = _s_timers0;
     70 }
     71 
     72 static SysTimer
     73 sys_timer_alloc( void )
     74 {
     75     SysTimer  timer = _s_free_timers;
     76 
     77     if (timer != NULL) {
     78         _s_free_timers = timer->next;
     79         timer->next    = NULL;
     80         timer->timer   = NULL;
     81     }
     82     return timer;
     83 }
     84 
     85 
     86 static void
     87 sys_timer_free( SysTimer  timer )
     88 {
     89     if (timer->timer) {
     90         qemu_del_timer( timer->timer );
     91         qemu_free_timer( timer->timer );
     92         timer->timer = NULL;
     93     }
     94     timer->next    = _s_free_timers;
     95     _s_free_timers = timer;
     96 }
     97 
     98 
     99 SysTimer   sys_timer_create( void )
    100 {
    101     SysTimer  timer = sys_timer_alloc();
    102     return timer;
    103 }
    104 
    105 void
    106 sys_timer_set( SysTimer  timer, SysTime  when, SysCallback   _callback, void*  opaque )
    107 {
    108     QEMUTimerCB*  callback = (QEMUTimerCB*)_callback;
    109 
    110     if (callback == NULL) {  /* unsetting the timer */
    111         if (timer->timer) {
    112             qemu_del_timer( timer->timer );
    113             qemu_free_timer( timer->timer );
    114             timer->timer = NULL;
    115         }
    116         timer->callback = callback;
    117         timer->opaque   = NULL;
    118         return;
    119     }
    120 
    121     if ( timer->timer ) {
    122          if ( timer->callback == callback && timer->opaque == opaque )
    123             goto ReuseTimer;
    124 
    125          /* need to replace the timer */
    126          qemu_free_timer( timer->timer );
    127     }
    128 
    129     timer->timer    = qemu_new_timer_ms( rt_clock, callback, opaque );
    130     timer->callback = callback;
    131     timer->opaque   = opaque;
    132 
    133 ReuseTimer:
    134     qemu_mod_timer( timer->timer, when );
    135 }
    136 
    137 void
    138 sys_timer_unset( SysTimer  timer )
    139 {
    140     if (timer->timer) {
    141         qemu_del_timer( timer->timer );
    142     }
    143 }
    144 
    145 void
    146 sys_timer_destroy( SysTimer  timer )
    147 {
    148     sys_timer_free( timer );
    149 }
    150 
    151 
    152 /** CHANNELS
    153  **/
    154 
    155 typedef struct SysChannelRec_ {
    156     int                 fd;
    157     SysChannelCallback  callback;
    158     void*               opaque;
    159     SysChannel          next;
    160 } SysChannelRec;
    161 
    162 #define  MAX_CHANNELS  16
    163 
    164 static SysChannelRec  _s_channels0[ MAX_CHANNELS ];
    165 static SysChannel     _s_free_channels;
    166 
    167 static void
    168 sys_init_channels( void )
    169 {
    170     int  nn;
    171 
    172     for ( nn = 0; nn < MAX_CHANNELS-1; nn++ ) {
    173         _s_channels0[nn].next = _s_channels0 + (nn+1);
    174     }
    175     _s_free_channels = _s_channels0;
    176 }
    177 
    178 static SysChannel
    179 sys_channel_alloc( )
    180 {
    181     SysChannel  channel = _s_free_channels;
    182     if (channel != NULL) {
    183         _s_free_channels  = channel->next;
    184         channel->next     = NULL;
    185         channel->fd       = -1;
    186         channel->callback = NULL;
    187         channel->opaque   = NULL;
    188     }
    189     return channel;
    190 }
    191 
    192 static void
    193 sys_channel_free( SysChannel  channel )
    194 {
    195     if (channel->fd >= 0) {
    196         socket_close( channel->fd );
    197         channel->fd = -1;
    198     }
    199     channel->next    = _s_free_channels;
    200     _s_free_channels = channel;
    201 }
    202 
    203 
    204 static void
    205 sys_channel_read_handler( void*  _channel )
    206 {
    207     SysChannel  channel = _channel;
    208     D( "%s: read event for channel %p:%d\n", __FUNCTION__,
    209        channel, channel->fd );
    210     channel->callback( channel->opaque, SYS_EVENT_READ );
    211 }
    212 
    213 static void
    214 sys_channel_write_handler( void*  _channel )
    215 {
    216     SysChannel  channel = _channel;
    217     D( "%s: write event for channel %p:%d\n", __FUNCTION__, channel, channel->fd );
    218     channel->callback( channel->opaque, SYS_EVENT_WRITE );
    219 }
    220 
    221 void
    222 sys_channel_on( SysChannel          channel,
    223                 int                 events,
    224                 SysChannelCallback  event_callback,
    225                 void*               event_opaque )
    226 {
    227     IOHandler*  read_handler  = NULL;
    228     IOHandler*  write_handler = NULL;
    229 
    230     if (events & SYS_EVENT_READ) {
    231         read_handler = sys_channel_read_handler;
    232     }
    233     if (events & SYS_EVENT_WRITE) {
    234         write_handler = sys_channel_write_handler;
    235     }
    236     channel->callback = event_callback;
    237     channel->opaque   = event_opaque;
    238     qemu_set_fd_handler( channel->fd, read_handler, write_handler, channel );
    239 }
    240 
    241 int
    242 sys_channel_read( SysChannel  channel, void*  buffer, int  size )
    243 {
    244     int   len = size;
    245     char* buf = (char*) buffer;
    246 
    247     while (len > 0) {
    248         int  ret = socket_recv(channel->fd, buf, len);
    249         if (ret < 0) {
    250             if (errno == EINTR)
    251                 continue;
    252             if (errno == EWOULDBLOCK || errno == EAGAIN)
    253                 break;
    254             D( "%s: after reading %d bytes, recv() returned error %d: %s\n",
    255                 __FUNCTION__, size - len, errno, errno_str);
    256             return -1;
    257         } else if (ret == 0) {
    258             break;
    259         } else {
    260             buf += ret;
    261             len -= ret;
    262         }
    263     }
    264     return size - len;
    265 }
    266 
    267 
    268 int
    269 sys_channel_write( SysChannel  channel, const void*  buffer, int  size )
    270 {
    271     int         len = size;
    272     const char* buf = (const char*) buffer;
    273 
    274     while (len > 0) {
    275         int  ret = socket_send(channel->fd, buf, len);
    276         if (ret < 0) {
    277             if (errno == EINTR)
    278                 continue;
    279             if (errno == EWOULDBLOCK || errno == EAGAIN)
    280                 break;
    281             D( "%s: send() returned error %d: %s\n",
    282                 __FUNCTION__, errno, errno_str);
    283             return -1;
    284         } else if (ret == 0) {
    285             break;
    286         } else {
    287             buf += ret;
    288             len -= ret;
    289         }
    290     }
    291     return size - len;
    292 }
    293 
    294 void  sys_channel_close( SysChannel  channel )
    295 {
    296     qemu_set_fd_handler( channel->fd, NULL, NULL, NULL );
    297     sys_channel_free( channel );
    298 }
    299 
    300 void  sys_main_init( void )
    301 {
    302     sys_init_channels();
    303     sys_init_timers();
    304 }
    305 
    306 
    307 int   sys_main_loop( void )
    308 {
    309     /* no looping, qemu has its own event loop */
    310     return 0;
    311 }
    312 
    313 
    314 
    315 
    316 SysChannel
    317 sys_channel_create_tcp_server( int port )
    318 {
    319     SysChannel  channel = sys_channel_alloc();
    320 
    321     channel->fd = socket_anyaddr_server( port, SOCKET_STREAM );
    322     if (channel->fd < 0) {
    323         D( "%s: failed to created network socket on TCP:%d\n",
    324             __FUNCTION__, port );
    325         sys_channel_free( channel );
    326         return NULL;
    327     }
    328 
    329     D( "%s: server channel %p:%d now listening on port %d\n",
    330        __FUNCTION__, channel, channel->fd, port );
    331 
    332     return channel;
    333 }
    334 
    335 
    336 SysChannel
    337 sys_channel_create_tcp_handler( SysChannel  server_channel )
    338 {
    339     SysChannel  channel = sys_channel_alloc();
    340 
    341     D( "%s: creating handler from server channel %p:%d\n", __FUNCTION__,
    342        server_channel, server_channel->fd );
    343 
    344     channel->fd = socket_accept_any( server_channel->fd );
    345     if (channel->fd < 0) {
    346         perror( "accept" );
    347         sys_channel_free( channel );
    348         return NULL;
    349     }
    350 
    351     /* disable Nagle algorithm */
    352     socket_set_nodelay( channel->fd );
    353 
    354     D( "%s: handler %p:%d created from server %p:%d\n", __FUNCTION__,
    355         server_channel, server_channel->fd, channel, channel->fd );
    356 
    357      return channel;
    358 }
    359 
    360 
    361 SysChannel
    362 sys_channel_create_tcp_client( const char*  hostname, int  port )
    363 {
    364     SysChannel  channel = sys_channel_alloc();
    365 
    366     channel->fd = socket_network_client( hostname, port, SOCKET_STREAM );
    367     if (channel->fd < 0) {
    368         sys_channel_free(channel);
    369         return NULL;
    370     };
    371 
    372     /* set to non-blocking and disable Nagle algorithm */
    373     socket_set_nonblock( channel->fd );
    374     socket_set_nodelay( channel->fd );
    375 
    376     return channel;
    377 }
    378 
    379