diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:35 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:35 -0800 |
commit | f721e3ac031f892af46f255a47d7f54a91317b30 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /telephony/sysdeps_posix.c | |
parent | bae1bc39312d5019bd9a5b8d840a529213a69a17 (diff) | |
download | external_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.zip external_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.tar.gz external_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'telephony/sysdeps_posix.c')
-rw-r--r-- | telephony/sysdeps_posix.c | 645 |
1 files changed, 0 insertions, 645 deletions
diff --git a/telephony/sysdeps_posix.c b/telephony/sysdeps_posix.c deleted file mode 100644 index 8c5eb12..0000000 --- a/telephony/sysdeps_posix.c +++ /dev/null @@ -1,645 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -*/ -#include "sysdeps.h" -#include <assert.h> -#include <unistd.h> -#include <sys/select.h> -#include <errno.h> -#include <memory.h> -#include <stdio.h> -#ifndef HAVE_WINSOCK -#include <fcntl.h> -#include <sys/socket.h> -#include <sys/select.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <netdb.h> -#endif - -/** QUEUE - **/ -#define SYS_MAX_QUEUE 16 - -typedef struct { - int start; - int end; - void* pending[ SYS_MAX_QUEUE ]; -} -SysQueueRec, *SysQueue; - -static void -sys_queue_reset( SysQueue queue ) -{ - queue->start = queue->end = 0; -} - -static void -sys_queue_add( SysQueue queue, void* item ) -{ - assert( queue->end - queue->start < SYS_MAX_QUEUE ); - assert( queue->start == 0 ); - assert( item != NULL ); - queue->pending[ queue->end++ ] = item; -} - -#if 0 -static void -sys_queue_remove( SysQueue queue, void* item ) -{ - int nn, count; - assert( queue->end > queue->start ); - assert( item != NULL ); - count = queue->end - queue->start; - for ( nn = queue->start; count > 0; ++nn, --count ) { - if ( queue->pending[nn] == item ) { - queue->pending[nn] = queue->pending[nn+count-1]; - queue->end -= 1; - break; - } - } - assert( 0 && "sys_queue_remove: item not found" ); -} -#endif - -static void* -sys_queue_get( SysQueue queue ) -{ - if (queue->end > queue->start) { - return queue->pending[ queue->start++ ]; - } - return NULL; -} - -/** CHANNELS - **/ -typedef struct SysChannelRec_ { - SysChannel next; - int fd; - char active; - char pending; - char closed; - int wanted; - int ready; - SysChannelCallback callback; - void* opaque; -} SysChannelRec; - - -/*** channel allocation ***/ -#define SYS_EVENT_MAX 3 -#define SYS_MAX_CHANNELS 16 - -static SysChannelRec _s_channels0[ SYS_MAX_CHANNELS ]; -static SysChannel _s_free_channels; - -static SysChannel -sys_channel_alloc( void ) -{ - SysChannel channel = _s_free_channels; - assert( channel != NULL && "out of free channels" ); - _s_free_channels = channel->next; - channel->next = NULL; - channel->active = 0; - channel->closed = 0; - channel->pending = 0; - channel->wanted = 0; - return channel; -} - -static void -sys_channel_free( SysChannel channel ) -{ - if (channel->fd >= 0) { -#ifdef _WIN32 - shutdown( channel->fd, SD_BOTH ); -#else - shutdown( channel->fd, SHUT_RDWR ); -#endif - close(channel->fd); - channel->fd = -1; - } - channel->wanted = 0; - channel->ready = 0; - channel->callback = NULL; - - channel->next = _s_free_channels; - _s_free_channels = channel; -} - - -/* list of active channels */ -static SysChannel _s_channels; - -/* used by select to wait on channel events */ -static fd_set _s_fdsets[SYS_EVENT_MAX]; -static int _s_maxfd; - -static void -sys_channel_deactivate( SysChannel channel ) -{ - assert( channel->active != 0 ); - SysChannel *pnode = &_s_channels; - for (;;) { - SysChannel node = *pnode; - assert( node != NULL ); - if (node == channel) - break; - pnode = &node->next; - } - *pnode = channel->next; - channel->next = NULL; - channel->active = 0; -} - -static void -sys_channel_activate( SysChannel channel ) -{ - assert( channel->active == 0 ); - channel->next = _s_channels; - _s_channels = channel; - channel->active = 1; - if (channel->fd > _s_maxfd) - _s_maxfd = channel->fd; -} - - -/* queue of pending channels */ -static SysQueueRec _s_pending_channels[1]; - - -static void -sys_init_channels( void ) -{ - int nn; - - for (nn = 0; nn < SYS_MAX_CHANNELS-1; nn++) - _s_channels0[nn].next = &_s_channels0[nn+1]; - _s_free_channels = &_s_channels0[0]; - - for (nn = 0; nn < SYS_EVENT_MAX; nn++) - FD_ZERO( &_s_fdsets[nn] ); - - _s_maxfd = -1; - - sys_queue_reset( _s_pending_channels ); -} - - -void -sys_channel_on( SysChannel channel, - int events, - SysChannelCallback callback, - void* opaque ) -{ - int adds = events & ~channel->wanted; - int removes = channel->wanted & ~events; - - channel->wanted = events; - channel->callback = callback; - channel->opaque = opaque; - - /* update global fdsets */ - if (adds) { - int ee; - for (ee = 0; ee < SYS_EVENT_MAX; ee++) - if (adds & (1 << ee)) - FD_SET( channel->fd, &_s_fdsets[ee] ); - } - if (removes) { - int ee; - for (ee = 0; ee < SYS_EVENT_MAX; ee++) - if (removes & (1 << ee)) - FD_CLR( channel->fd, &_s_fdsets[ee] ); - } - if (events && !channel->active) { - sys_channel_activate( channel ); - } - else if (!events && channel->active) { - sys_channel_deactivate( channel ); - } -} - -int -sys_channel_read( SysChannel channel, void* buffer, int size ) -{ - char* buff = buffer; - int count = 0; - - assert( !channel->closed ); - - while (size > 0) { - int len = read(channel->fd, buff, size); - if (len < 0) { - if (errno == EINTR) - continue; - if (count == 0) - count = -1; - break; - } - buff += len; - size -= len; - count += len; - } - return count; -} - - -int -sys_channel_write( SysChannel channel, const void* buffer, int size ) -{ - const char* buff = buffer; - int count = 0; - - assert( !channel->closed ); - - while (size > 0) { - int len = write(channel->fd, buff, size); - if (len < 0) { - if (errno == EINTR) - continue; - if (count == 0) - count = -1; - break; - } - buff += len; - size -= len; - count += len; - } - return count; -} - - -void -sys_channel_close( SysChannel channel ) -{ - if (channel->active) { - sys_channel_on( channel, 0, NULL, NULL ); - } - - if (channel->pending) { - /* we can't free the channel right now because it */ - /* is in the pending list, set a flag */ - channel->closed = 1; - return; - } - - if (!channel->closed) { - channel->closed = 1; - } - - sys_channel_free( channel ); -} - -/** time measurement - **/ -SysTime sys_time_ms( void ) -{ - struct timeval tv; - gettimeofday( &tv, NULL ); - return (SysTime)(tv.tv_usec / 1000) + (SysTime)tv.tv_sec * 1000; -} - -/** timers - **/ -typedef struct SysTimerRec_ -{ - SysTimer next; - SysTime when; - SysCallback callback; - void* opaque; -} SysTimerRec; - -#define SYS_MAX_TIMERS 16 - -static SysTimerRec _s_timers0[ SYS_MAX_TIMERS ]; -static SysTimer _s_free_timers; -static SysTimer _s_timers; - -static SysQueueRec _s_pending_timers[1]; - - -static void -sys_init_timers( void ) -{ - int nn; - for (nn = 0; nn < SYS_MAX_TIMERS-1; nn++) { - _s_timers0[nn].next = & _s_timers0[nn+1]; - } - _s_free_timers = &_s_timers0[0]; - - sys_queue_reset( _s_pending_timers ); -} - - -SysTimer sys_timer_create( void ) -{ - SysTimer timer = _s_free_timers; - assert( timer != NULL && "too many timers allocated" ); - _s_free_timers = timer->next; - timer->next = NULL; - return timer; -} - - -void sys_timer_unset( SysTimer timer ) -{ - if (timer->callback != NULL) { - SysTimer *pnode, node; - pnode = &_s_timers; - for (;;) { - node = *pnode; - if (node == NULL) - break; - if (node == timer) { - *pnode = node->next; - break; - } - pnode = &node->next; - } - timer->next = NULL; - timer->callback = NULL; - timer->opaque = NULL; - } -} - - -void sys_timer_set( SysTimer timer, - SysTime when, - SysCallback callback, - void* opaque ) -{ - if (timer->callback != NULL) - sys_timer_unset(timer); - - if (callback != NULL) { - SysTime now = sys_time_ms(); - - if (now >= when) { - callback( opaque ); - } else { - SysTimer *pnode, node; - pnode = &_s_timers; - for (;;) { - node = *pnode; - if (node == NULL || node->when >= when) { - break; - } - pnode = &node->next; - } - timer->next = *pnode; - *pnode = timer; - timer->when = when; - timer->callback = callback; - timer->opaque = opaque; - } - } -} - - -void sys_timer_destroy( SysTimer timer ) -{ - assert( timer != NULL && "sys_timer_destroy: bad argument" ); - if (timer->callback != NULL) - sys_timer_unset(timer); - - timer->next = _s_free_timers; - _s_free_timers = timer; -} - - -static void -sys_single_loop( void ) -{ - fd_set rfd, wfd, efd; - struct timeval timeout_tv, *timeout = NULL; - int n; - - memcpy(&rfd, &_s_fdsets[0], sizeof(fd_set)); - memcpy(&wfd, &_s_fdsets[1], sizeof(fd_set)); - memcpy(&efd, &_s_fdsets[2], sizeof(fd_set)); - - if ( _s_timers != NULL ) { - SysTime now = sys_time_ms(); - SysTimer first = _s_timers; - - timeout = &timeout_tv; - if (first->when <= now) { - timeout->tv_sec = 0; - timeout->tv_usec = 0; - } else { - SysTime diff = first->when - now; - timeout->tv_sec = diff / 1000; - timeout->tv_usec = (diff - timeout->tv_sec*1000) * 1000; - } - } - - n = select( _s_maxfd+1, &rfd, &wfd, &efd, timeout); - if(n < 0) { - if(errno == EINTR) return; - perror("select"); - return; - } - - /* enqueue pending channels */ - { - int i; - - sys_queue_reset( _s_pending_channels ); - for(i = 0; (i <= _s_maxfd) && (n > 0); i++) - { - int events = 0; - - if(FD_ISSET(i, &rfd)) events |= SYS_EVENT_READ; - if(FD_ISSET(i, &wfd)) events |= SYS_EVENT_WRITE; - if(FD_ISSET(i, &efd)) events |= SYS_EVENT_ERROR; - - if (events) { - SysChannel channel; - - n--; - for (channel = _s_channels; channel; channel = channel->next) - { - if (channel->fd != i) - continue; - - channel->ready = events; - channel->pending = 1; - sys_queue_add( _s_pending_channels, channel ); - break; - } - } - } - } - - /* enqueue pending timers */ - { - SysTimer timer = _s_timers; - SysTime now = sys_time_ms(); - - sys_queue_reset( _s_pending_timers ); - while (timer != NULL) - { - if (timer->when > now) - break; - - sys_queue_add( _s_pending_timers, timer ); - _s_timers = timer = timer->next; - } - } -} - -void sys_main_init( void ) -{ - sys_init_channels(); - sys_init_timers(); -} - - -int sys_main_loop( void ) -{ - for (;;) { - SysTimer timer; - SysChannel channel; - - /* exit if we have nothing to do */ - if (_s_channels == NULL && _s_timers == NULL) - break; - - sys_single_loop(); - - while ((timer = sys_queue_get( _s_pending_timers )) != NULL) { - timer->callback( timer->opaque ); - } - - while ((channel = sys_queue_get( _s_pending_channels )) != NULL) { - int events; - - channel->pending = 0; - if (channel->closed) { - /* the channel was closed by a previous callback */ - sys_channel_close(channel); - } - events = channel->ready; - channel->ready = 0; - channel->callback( channel->opaque, events ); - } - } - return 0; -} - - - - -SysChannel -sys_channel_create_tcp_server( int port ) -{ - SysChannel channel; - int on = 1; - const int BACKLOG = 4; - - channel = sys_channel_alloc(); - if (-1==(channel->fd=socket(AF_INET, SOCK_STREAM, 0))) { - perror("socket"); - sys_channel_free( channel ); - return NULL; - } - - /* Enable address re-use for server mode */ - if ( -1==setsockopt( channel->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) )) { - perror("setsockopt(SO_REUSEADDR)"); - } - - { - struct sockaddr_in servname; - long in_addr = INADDR_ANY; - - servname.sin_family = AF_INET; - servname.sin_port = htons(port); - - servname.sin_addr.s_addr=in_addr; - - if (-1==bind(channel->fd, (struct sockaddr*)&servname, sizeof(servname))) { - perror("bind"); - sys_channel_close(channel); - return NULL; - } - - /* Listen but don't accept */ - if ( listen(channel->fd, BACKLOG) < 0 ) { - perror("listen"); - sys_channel_close(channel); - return NULL; - } - } - return channel; -} - - -SysChannel -sys_channel_create_tcp_handler( SysChannel server_channel ) -{ - int on = 1; - SysChannel channel = sys_channel_alloc(); - - channel->fd = accept( server_channel->fd, NULL, 0 ); - if (channel->fd < 0) { - perror( "accept" ); - sys_channel_free( channel ); - return NULL; - } - - /* set to non-blocking and disable TCP Nagle algorithm */ - fcntl(channel->fd, F_SETFL, O_NONBLOCK); - setsockopt(channel->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); - return channel; -} - - -SysChannel -sys_channel_create_tcp_client( const char* hostname, int port ) -{ - struct hostent* hp; - struct sockaddr_in addr; - SysChannel channel = sys_channel_alloc(); - int on = 1; - - hp = gethostbyname(hostname); - if(hp == 0) { - fprintf(stderr, "unknown host: %s\n", hostname); - sys_channel_free(channel); - return NULL; - }; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = hp->h_addrtype; - addr.sin_port = htons(port); - memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); - - channel->fd = socket(hp->h_addrtype, SOCK_STREAM, 0); - if(channel->fd < 0) { - sys_channel_free(channel); - return NULL; - } - - if(connect( channel->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror( "connect" ); - sys_channel_free(channel); - return NULL; - } - - /* set to non-blocking and disable Nagle algorithm */ - fcntl(channel->fd, F_SETFL, O_NONBLOCK); - setsockopt( channel->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on) ); - return channel; -} - |