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 41SysTime 42sys_time_ms( void ) 43{ 44 return qemu_get_clock_ms(rt_clock); 45} 46 47/** TIMERS 48 **/ 49 50typedef struct SysTimerRec_ { 51 QEMUTimer* timer; 52 QEMUTimerCB* callback; 53 void* opaque; 54 SysTimer next; 55} SysTimerRec; 56 57#define MAX_TIMERS 32 58 59static SysTimerRec _s_timers0[ MAX_TIMERS ]; 60static SysTimer _s_free_timers; 61 62static void 63sys_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 72static SysTimer 73sys_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 86static void 87sys_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 99SysTimer sys_timer_create( void ) 100{ 101 SysTimer timer = sys_timer_alloc(); 102 return timer; 103} 104 105void 106sys_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 133ReuseTimer: 134 qemu_mod_timer( timer->timer, when ); 135} 136 137void 138sys_timer_unset( SysTimer timer ) 139{ 140 if (timer->timer) { 141 qemu_del_timer( timer->timer ); 142 } 143} 144 145void 146sys_timer_destroy( SysTimer timer ) 147{ 148 sys_timer_free( timer ); 149} 150 151 152/** CHANNELS 153 **/ 154 155typedef struct SysChannelRec_ { 156 int fd; 157 SysChannelCallback callback; 158 void* opaque; 159 SysChannel next; 160} SysChannelRec; 161 162#define MAX_CHANNELS 16 163 164static SysChannelRec _s_channels0[ MAX_CHANNELS ]; 165static SysChannel _s_free_channels; 166 167static void 168sys_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 178static SysChannel 179sys_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 192static void 193sys_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 204static void 205sys_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 213static void 214sys_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 221void 222sys_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 241int 242sys_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 268int 269sys_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 294void sys_channel_close( SysChannel channel ) 295{ 296 qemu_set_fd_handler( channel->fd, NULL, NULL, NULL ); 297 sys_channel_free( channel ); 298} 299 300void sys_main_init( void ) 301{ 302 sys_init_channels(); 303 sys_init_timers(); 304} 305 306 307int sys_main_loop( void ) 308{ 309 /* no looping, qemu has its own event loop */ 310 return 0; 311} 312 313 314 315 316SysChannel 317sys_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 336SysChannel 337sys_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 361SysChannel 362sys_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