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 "sysdeps.h"
     13 #include <assert.h>
     14 #include <unistd.h>
     15 #include <sys/select.h>
     16 #include <errno.h>
     17 #include <memory.h>
     18 #include <stdio.h>
     19 #ifndef HAVE_WINSOCK
     20 #include <fcntl.h>
     21 #include <sys/socket.h>
     22 #include <sys/select.h>
     23 #include <sys/types.h>
     24 #include <netinet/in.h>
     25 #include <netinet/tcp.h>
     26 #include <netdb.h>
     27 #endif
     28 
     29 /**  QUEUE
     30  **/
     31 #define  SYS_MAX_QUEUE  16
     32 
     33 typedef struct {
     34     int    start;
     35     int    end;
     36     void*  pending[ SYS_MAX_QUEUE ];
     37 }
     38 SysQueueRec, *SysQueue;
     39 
     40 static void
     41 sys_queue_reset( SysQueue  queue )
     42 {
     43     queue->start = queue->end = 0;
     44 }
     45 
     46 static void
     47 sys_queue_add( SysQueue  queue, void*  item )
     48 {
     49     assert( queue->end - queue->start < SYS_MAX_QUEUE );
     50     assert( queue->start == 0 );
     51     assert( item != NULL );
     52     queue->pending[ queue->end++ ] = item;
     53 }
     54 
     55 #if 0
     56 static void
     57 sys_queue_remove( SysQueue  queue, void*  item )
     58 {
     59     int  nn, count;
     60     assert( queue->end > queue->start );
     61     assert( item != NULL );
     62     count = queue->end - queue->start;
     63     for ( nn = queue->start; count > 0; ++nn, --count ) {
     64         if ( queue->pending[nn] == item ) {
     65             queue->pending[nn] = queue->pending[nn+count-1];
     66             queue->end -= 1;
     67             break;
     68         }
     69     }
     70     assert( 0 && "sys_queue_remove: item not found" );
     71 }
     72 #endif
     73 
     74 static void*
     75 sys_queue_get( SysQueue  queue )
     76 {
     77     if (queue->end > queue->start) {
     78         return queue->pending[ queue->start++ ];
     79     }
     80     return NULL;
     81 }
     82 
     83 /** CHANNELS
     84  **/
     85 typedef struct SysChannelRec_ {
     86     SysChannel          next;
     87     int                 fd;
     88     char                active;
     89     char                pending;
     90     char                closed;
     91     int                 wanted;
     92     int                 ready;
     93     SysChannelCallback  callback;
     94     void*               opaque;
     95 } SysChannelRec;
     96 
     97 
     98 /*** channel allocation ***/
     99 #define  SYS_EVENT_MAX     3
    100 #define  SYS_MAX_CHANNELS  16
    101 
    102 static SysChannelRec  _s_channels0[ SYS_MAX_CHANNELS ];
    103 static SysChannel     _s_free_channels;
    104 
    105 static SysChannel
    106 sys_channel_alloc( void )
    107 {
    108     SysChannel  channel = _s_free_channels;
    109     assert( channel != NULL && "out of free channels" );
    110     _s_free_channels  = channel->next;
    111     channel->next     = NULL;
    112     channel->active   = 0;
    113     channel->closed   = 0;
    114     channel->pending  = 0;
    115     channel->wanted   = 0;
    116     return channel;
    117 }
    118 
    119 static void
    120 sys_channel_free( SysChannel  channel )
    121 {
    122     if (channel->fd >= 0) {
    123 #ifdef _WIN32
    124         shutdown( channel->fd, SD_BOTH );
    125 #else
    126         shutdown( channel->fd, SHUT_RDWR );
    127 #endif
    128         close(channel->fd);
    129         channel->fd = -1;
    130     }
    131     channel->wanted   = 0;
    132     channel->ready    = 0;
    133     channel->callback = NULL;
    134 
    135     channel->next    = _s_free_channels;
    136     _s_free_channels = channel;
    137 }
    138 
    139 
    140 /* list of active channels */
    141 static SysChannel     _s_channels;
    142 
    143 /* used by select to wait on channel events */
    144 static fd_set         _s_fdsets[SYS_EVENT_MAX];
    145 static int            _s_maxfd;
    146 
    147 static void
    148 sys_channel_deactivate( SysChannel  channel )
    149 {
    150     assert( channel->active != 0 );
    151     SysChannel  *pnode = &_s_channels;
    152     for (;;) {
    153         SysChannel  node = *pnode;
    154         assert( node != NULL );
    155         if (node == channel)
    156             break;
    157         pnode = &node->next;
    158     }
    159     *pnode          = channel->next;
    160     channel->next   = NULL;
    161     channel->active = 0;
    162 }
    163 
    164 static void
    165 sys_channel_activate( SysChannel  channel )
    166 {
    167     assert( channel->active == 0 );
    168     channel->next = _s_channels;
    169     _s_channels   = channel;
    170     channel->active = 1;
    171     if (channel->fd > _s_maxfd)
    172         _s_maxfd = channel->fd;
    173 }
    174 
    175 
    176 /* queue of pending channels */
    177 static SysQueueRec    _s_pending_channels[1];
    178 
    179 
    180 static void
    181 sys_init_channels( void )
    182 {
    183     int  nn;
    184 
    185     for (nn = 0; nn < SYS_MAX_CHANNELS-1; nn++)
    186         _s_channels0[nn].next = &_s_channels0[nn+1];
    187     _s_free_channels = &_s_channels0[0];
    188 
    189     for (nn = 0; nn < SYS_EVENT_MAX; nn++)
    190         FD_ZERO( &_s_fdsets[nn] );
    191 
    192     _s_maxfd = -1;
    193 
    194     sys_queue_reset( _s_pending_channels );
    195 }
    196 
    197 
    198 void
    199 sys_channel_on( SysChannel          channel,
    200                 int                 events,
    201                 SysChannelCallback  callback,
    202                 void*               opaque )
    203 {
    204     int   adds    = events & ~channel->wanted;
    205     int   removes = channel->wanted & ~events;
    206 
    207     channel->wanted   = events;
    208     channel->callback = callback;
    209     channel->opaque   = opaque;
    210 
    211     /* update global fdsets */
    212     if (adds) {
    213         int  ee;
    214         for (ee = 0; ee < SYS_EVENT_MAX; ee++)
    215             if (adds & (1 << ee))
    216                 FD_SET( channel->fd, &_s_fdsets[ee] );
    217     }
    218     if (removes) {
    219         int  ee;
    220         for (ee = 0; ee < SYS_EVENT_MAX; ee++)
    221             if (removes & (1 << ee))
    222                 FD_CLR( channel->fd, &_s_fdsets[ee] );
    223     }
    224     if (events && !channel->active) {
    225         sys_channel_activate( channel );
    226     }
    227     else if (!events && channel->active) {
    228         sys_channel_deactivate( channel );
    229     }
    230 }
    231 
    232 int
    233 sys_channel_read( SysChannel  channel, void*  buffer, int  size )
    234 {
    235     char*  buff = buffer;
    236     int    count = 0;
    237 
    238     assert( !channel->closed );
    239 
    240     while (size > 0) {
    241         int  len = read(channel->fd, buff, size);
    242         if (len < 0) {
    243             if (errno == EINTR)
    244                 continue;
    245             if (count == 0)
    246                 count = -1;
    247             break;
    248         }
    249         buff  += len;
    250         size  -= len;
    251         count += len;
    252     }
    253     return count;
    254 }
    255 
    256 
    257 int
    258 sys_channel_write( SysChannel  channel, const void*  buffer, int  size )
    259 {
    260     const char*  buff = buffer;
    261     int          count = 0;
    262 
    263     assert( !channel->closed );
    264 
    265     while (size > 0) {
    266         int  len = write(channel->fd, buff, size);
    267         if (len < 0) {
    268             if (errno == EINTR)
    269                 continue;
    270             if (count == 0)
    271                 count = -1;
    272             break;
    273         }
    274         buff  += len;
    275         size  -= len;
    276         count += len;
    277     }
    278     return count;
    279 }
    280 
    281 
    282 void
    283 sys_channel_close( SysChannel  channel )
    284 {
    285     if (channel->active) {
    286         sys_channel_on( channel, 0, NULL, NULL );
    287     }
    288 
    289     if (channel->pending) {
    290         /* we can't free the channel right now because it */
    291         /* is in the pending list, set a flag             */
    292         channel->closed = 1;
    293         return;
    294     }
    295 
    296     if (!channel->closed) {
    297         channel->closed = 1;
    298     }
    299 
    300     sys_channel_free( channel );
    301 }
    302 
    303 /** time measurement
    304  **/
    305 SysTime  sys_time_ms( void )
    306 {
    307     struct timeval  tv;
    308     gettimeofday( &tv, NULL );
    309     return (SysTime)(tv.tv_usec / 1000) + (SysTime)tv.tv_sec * 1000;
    310 }
    311 
    312 /** timers
    313  **/
    314 typedef struct SysTimerRec_
    315 {
    316     SysTimer     next;
    317     SysTime      when;
    318     SysCallback  callback;
    319     void*        opaque;
    320 } SysTimerRec;
    321 
    322 #define  SYS_MAX_TIMERS  16
    323 
    324 static SysTimerRec   _s_timers0[ SYS_MAX_TIMERS ];
    325 static SysTimer      _s_free_timers;
    326 static SysTimer      _s_timers;
    327 
    328 static SysQueueRec   _s_pending_timers[1];
    329 
    330 
    331 static void
    332 sys_init_timers( void )
    333 {
    334     int  nn;
    335     for (nn = 0; nn < SYS_MAX_TIMERS-1; nn++) {
    336         _s_timers0[nn].next = & _s_timers0[nn+1];
    337     }
    338     _s_free_timers = &_s_timers0[0];
    339 
    340     sys_queue_reset( _s_pending_timers );
    341 }
    342 
    343 
    344 SysTimer   sys_timer_create( void )
    345 {
    346     SysTimer  timer = _s_free_timers;
    347     assert( timer != NULL && "too many timers allocated" );
    348     _s_free_timers = timer->next;
    349     timer->next    = NULL;
    350     return timer;
    351 }
    352 
    353 
    354 void  sys_timer_unset( SysTimer  timer )
    355 {
    356     if (timer->callback != NULL) {
    357         SysTimer  *pnode, node;
    358         pnode = &_s_timers;
    359         for (;;) {
    360             node = *pnode;
    361             if (node == NULL)
    362                 break;
    363             if (node == timer) {
    364                 *pnode = node->next;
    365                 break;
    366             }
    367             pnode = &node->next;
    368         }
    369         timer->next     = NULL;
    370         timer->callback = NULL;
    371         timer->opaque   = NULL;
    372     }
    373 }
    374 
    375 
    376 void  sys_timer_set( SysTimer      timer,
    377                      SysTime       when,
    378                      SysCallback   callback,
    379                      void*         opaque )
    380 {
    381     if (timer->callback != NULL)
    382         sys_timer_unset(timer);
    383 
    384     if (callback != NULL) {
    385         SysTime  now = sys_time_ms();
    386 
    387         if (now >= when) {
    388             callback( opaque );
    389         } else {
    390             SysTimer  *pnode, node;
    391             pnode = &_s_timers;
    392             for (;;) {
    393                 node = *pnode;
    394                 if (node == NULL || node->when >= when) {
    395                     break;
    396                 }
    397                 pnode = &node->next;
    398             }
    399             timer->next     = *pnode;
    400             *pnode          = timer;
    401             timer->when     = when;
    402             timer->callback = callback;
    403             timer->opaque   = opaque;
    404         }
    405     }
    406 }
    407 
    408 
    409 void  sys_timer_destroy( SysTimer  timer )
    410 {
    411     assert( timer != NULL && "sys_timer_destroy: bad argument" );
    412     if (timer->callback != NULL)
    413         sys_timer_unset(timer);
    414 
    415     timer->next    = _s_free_timers;
    416     _s_free_timers = timer;
    417 }
    418 
    419 
    420 static void
    421 sys_single_loop( void )
    422 {
    423     fd_set rfd, wfd, efd;
    424     struct timeval  timeout_tv, *timeout = NULL;
    425     int    n;
    426 
    427     memcpy(&rfd, &_s_fdsets[0], sizeof(fd_set));
    428     memcpy(&wfd, &_s_fdsets[1], sizeof(fd_set));
    429     memcpy(&efd, &_s_fdsets[2], sizeof(fd_set));
    430 
    431     if ( _s_timers != NULL ) {
    432         SysTime   now   = sys_time_ms();
    433         SysTimer  first = _s_timers;
    434 
    435         timeout = &timeout_tv;
    436         if (first->when <= now) {
    437             timeout->tv_sec  = 0;
    438             timeout->tv_usec = 0;
    439         } else {
    440             SysTime  diff = first->when - now;
    441             timeout->tv_sec =   diff / 1000;
    442             timeout->tv_usec = (diff - timeout->tv_sec*1000) * 1000;
    443         }
    444     }
    445 
    446     n = select( _s_maxfd+1, &rfd, &wfd, &efd, timeout);
    447     if(n < 0) {
    448         if(errno == EINTR) return;
    449         perror("select");
    450         return;
    451     }
    452 
    453     /* enqueue pending channels */
    454     {
    455         int  i;
    456 
    457         sys_queue_reset( _s_pending_channels );
    458         for(i = 0; (i <= _s_maxfd) && (n > 0); i++)
    459         {
    460             int  events = 0;
    461 
    462             if(FD_ISSET(i, &rfd)) events |= SYS_EVENT_READ;
    463             if(FD_ISSET(i, &wfd)) events |= SYS_EVENT_WRITE;
    464             if(FD_ISSET(i, &efd)) events |= SYS_EVENT_ERROR;
    465 
    466             if (events) {
    467                 SysChannel  channel;
    468 
    469                 n--;
    470                 for (channel = _s_channels; channel; channel = channel->next)
    471                 {
    472                     if (channel->fd != i)
    473                         continue;
    474 
    475                     channel->ready   = events;
    476                     channel->pending = 1;
    477                     sys_queue_add( _s_pending_channels, channel );
    478                     break;
    479                 }
    480             }
    481         }
    482     }
    483 
    484     /* enqueue pending timers */
    485     {
    486         SysTimer  timer = _s_timers;
    487         SysTime   now   = sys_time_ms();
    488 
    489         sys_queue_reset( _s_pending_timers );
    490         while (timer != NULL)
    491         {
    492             if (timer->when > now)
    493                 break;
    494 
    495             sys_queue_add( _s_pending_timers, timer );
    496             _s_timers = timer = timer->next;
    497         }
    498     }
    499 }
    500 
    501 void  sys_main_init( void )
    502 {
    503     sys_init_channels();
    504     sys_init_timers();
    505 }
    506 
    507 
    508 int   sys_main_loop( void )
    509 {
    510     for (;;) {
    511         SysTimer    timer;
    512         SysChannel  channel;
    513 
    514         /* exit if we have nothing to do */
    515         if (_s_channels == NULL && _s_timers == NULL)
    516             break;
    517 
    518         sys_single_loop();
    519 
    520         while ((timer = sys_queue_get( _s_pending_timers )) != NULL) {
    521             timer->callback( timer->opaque );
    522         }
    523 
    524         while ((channel = sys_queue_get( _s_pending_channels )) != NULL) {
    525             int  events;
    526 
    527             channel->pending = 0;
    528             if (channel->closed) {
    529                 /* the channel was closed by a previous callback */
    530                 sys_channel_close(channel);
    531             }
    532             events = channel->ready;
    533             channel->ready = 0;
    534             channel->callback( channel->opaque, events );
    535         }
    536     }
    537     return 0;
    538 }
    539 
    540 
    541 
    542 
    543 SysChannel
    544 sys_channel_create_tcp_server( int port )
    545 {
    546     SysChannel          channel;
    547     int                 on = 1;
    548     const int           BACKLOG = 4;
    549 
    550     channel = sys_channel_alloc();
    551     if (-1==(channel->fd=socket(AF_INET, SOCK_STREAM, 0))) {
    552         perror("socket");
    553         sys_channel_free( channel );
    554         return NULL;
    555     }
    556 
    557     /* Enable address re-use for server mode */
    558     if ( -1==setsockopt( channel->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) )) {
    559         perror("setsockopt(SO_REUSEADDR)");
    560     }
    561 
    562     {
    563         struct sockaddr_in  servname;
    564         long                in_addr = INADDR_ANY;
    565 
    566         servname.sin_family = AF_INET;
    567         servname.sin_port   = htons(port);
    568 
    569         servname.sin_addr.s_addr=in_addr;
    570 
    571         if (-1==bind(channel->fd, (struct sockaddr*)&servname, sizeof(servname))) {
    572             perror("bind");
    573             sys_channel_close(channel);
    574             return NULL;
    575         }
    576 
    577         /* Listen but don't accept */
    578         if ( listen(channel->fd, BACKLOG) < 0 ) {
    579             perror("listen");
    580             sys_channel_close(channel);
    581             return NULL;
    582         }
    583     }
    584     return channel;
    585 }
    586 
    587 
    588 SysChannel
    589 sys_channel_create_tcp_handler( SysChannel  server_channel )
    590 {
    591     int         on      = 1;
    592     SysChannel  channel = sys_channel_alloc();
    593 
    594     channel->fd = accept( server_channel->fd, NULL, 0 );
    595     if (channel->fd < 0) {
    596         perror( "accept" );
    597         sys_channel_free( channel );
    598         return NULL;
    599     }
    600 
    601     /* set to non-blocking and disable TCP Nagle algorithm */
    602     fcntl(channel->fd, F_SETFL, O_NONBLOCK);
    603     setsockopt(channel->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
    604     return channel;
    605 }
    606 
    607 
    608 SysChannel
    609 sys_channel_create_tcp_client( const char*  hostname, int  port )
    610 {
    611     struct hostent*     hp;
    612     struct sockaddr_in  addr;
    613     SysChannel          channel = sys_channel_alloc();
    614     int                 on = 1;
    615 
    616     hp = gethostbyname(hostname);
    617     if(hp == 0) {
    618         fprintf(stderr, "unknown host: %s\n", hostname);
    619         sys_channel_free(channel);
    620         return NULL;
    621     };
    622 
    623     memset(&addr, 0, sizeof(addr));
    624     addr.sin_family = hp->h_addrtype;
    625     addr.sin_port   = htons(port);
    626     memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
    627 
    628     channel->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
    629     if(channel->fd < 0) {
    630         sys_channel_free(channel);
    631         return NULL;
    632     }
    633 
    634     if(connect( channel->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    635         perror( "connect" );
    636         sys_channel_free(channel);
    637         return NULL;
    638     }
    639 
    640     /* set to non-blocking and disable Nagle algorithm */
    641     fcntl(channel->fd, F_SETFL, O_NONBLOCK);
    642     setsockopt( channel->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on) );
    643     return channel;
    644 }
    645 
    646