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 "android/sockets.h"
13#include "sysdeps.h"
14#include "qemu-common.h"
15#include "qemu/timer.h"
16#include "sysemu/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_clock_get_ms(QEMU_CLOCK_REALTIME);
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        timer_del( timer->timer );
91        timer_free( 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            timer_del( timer->timer );
113            timer_free( 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         timer_free( timer->timer );
127    }
128
129    timer->timer    = timer_new(QEMU_CLOCK_REALTIME, SCALE_MS, callback, opaque );
130    timer->callback = callback;
131    timer->opaque   = opaque;
132
133ReuseTimer:
134    timer_mod( timer->timer, when );
135}
136
137void
138sys_timer_unset( SysTimer  timer )
139{
140    if (timer->timer) {
141        timer_del( 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