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