• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-timer.h"
15 #include "qemu-char.h"
16 #ifdef _WIN32
17 #include <winsock2.h>
18 #else
19 #include <sys/socket.h>
20 #include <sys/select.h>
21 #include <sys/types.h>
22 #include <netinet/in.h>
23 #include <netinet/tcp.h>
24 #include <netdb.h>
25 #endif
26 
27 #define  DEBUG  0
28 
29 #define  D_ACTIVE  DEBUG
30 
31 #if DEBUG
32 #define  D(...)  do { if (D_ACTIVE) fprintf(stderr, __VA_ARGS__); } while (0)
33 #else
34 #define  D(...)  ((void)0)
35 #endif
36 
37 /** TIME
38  **/
39 
40 SysTime
sys_time_ms(void)41 sys_time_ms( void )
42 {
43     return qemu_get_clock( rt_clock );
44 }
45 
46 /** TIMERS
47  **/
48 
49 typedef struct SysTimerRec_ {
50     QEMUTimer*    timer;
51     QEMUTimerCB*  callback;
52     void*         opaque;
53     SysTimer      next;
54 } SysTimerRec;
55 
56 #define  MAX_TIMERS  32
57 
58 static SysTimerRec  _s_timers0[ MAX_TIMERS ];
59 static SysTimer     _s_free_timers;
60 
61 static void
sys_init_timers(void)62 sys_init_timers( void )
63 {
64     int  nn;
65     for (nn = 0; nn < MAX_TIMERS-1; nn++)
66         _s_timers0[nn].next = _s_timers0 + (nn+1);
67 
68     _s_free_timers = _s_timers0;
69 }
70 
71 static SysTimer
sys_timer_alloc(void)72 sys_timer_alloc( void )
73 {
74     SysTimer  timer = _s_free_timers;
75 
76     if (timer != NULL) {
77         _s_free_timers = timer->next;
78         timer->next    = NULL;
79         timer->timer   = NULL;
80     }
81     return timer;
82 }
83 
84 
85 static void
sys_timer_free(SysTimer timer)86 sys_timer_free( SysTimer  timer )
87 {
88     if (timer->timer) {
89         qemu_del_timer( timer->timer );
90         qemu_free_timer( timer->timer );
91         timer->timer = NULL;
92     }
93     timer->next    = _s_free_timers;
94     _s_free_timers = timer;
95 }
96 
97 
sys_timer_create(void)98 SysTimer   sys_timer_create( void )
99 {
100     SysTimer  timer = sys_timer_alloc();
101     return timer;
102 }
103 
104 void
sys_timer_set(SysTimer timer,SysTime when,SysCallback _callback,void * opaque)105 sys_timer_set( SysTimer  timer, SysTime  when, SysCallback   _callback, void*  opaque )
106 {
107     QEMUTimerCB*  callback = (QEMUTimerCB*)_callback;
108 
109     if (callback == NULL) {  /* unsetting the timer */
110         if (timer->timer) {
111             qemu_del_timer( timer->timer );
112             qemu_free_timer( timer->timer );
113             timer->timer = NULL;
114         }
115         timer->callback = callback;
116         timer->opaque   = NULL;
117         return;
118     }
119 
120     if ( timer->timer ) {
121          if ( timer->callback == callback && timer->opaque == opaque )
122             goto ReuseTimer;
123 
124          /* need to replace the timer */
125          qemu_free_timer( timer->timer );
126     }
127 
128     timer->timer    = qemu_new_timer( rt_clock, callback, opaque );
129     timer->callback = callback;
130     timer->opaque   = opaque;
131 
132 ReuseTimer:
133     qemu_mod_timer( timer->timer, when );
134 }
135 
136 void
sys_timer_unset(SysTimer timer)137 sys_timer_unset( SysTimer  timer )
138 {
139     if (timer->timer) {
140         qemu_del_timer( timer->timer );
141     }
142 }
143 
144 void
sys_timer_destroy(SysTimer timer)145 sys_timer_destroy( SysTimer  timer )
146 {
147     sys_timer_free( timer );
148 }
149 
150 
151 /** CHANNELS
152  **/
153 
154 typedef struct SysChannelRec_ {
155     int                 fd;
156     SysChannelCallback  callback;
157     void*               opaque;
158     SysChannel          next;
159 } SysChannelRec;
160 
161 #define  MAX_CHANNELS  16
162 
163 static SysChannelRec  _s_channels0[ MAX_CHANNELS ];
164 static SysChannel     _s_free_channels;
165 
166 static void
sys_init_channels(void)167 sys_init_channels( void )
168 {
169     int  nn;
170 
171     for ( nn = 0; nn < MAX_CHANNELS-1; nn++ ) {
172         _s_channels0[nn].next = _s_channels0 + (nn+1);
173     }
174     _s_free_channels = _s_channels0;
175 }
176 
177 static SysChannel
sys_channel_alloc()178 sys_channel_alloc( )
179 {
180     SysChannel  channel = _s_free_channels;
181     if (channel != NULL) {
182         _s_free_channels  = channel->next;
183         channel->next     = NULL;
184         channel->fd       = -1;
185         channel->callback = NULL;
186         channel->opaque   = NULL;
187     }
188     return channel;
189 }
190 
191 static void
sys_channel_free(SysChannel channel)192 sys_channel_free( SysChannel  channel )
193 {
194     if (channel->fd >= 0) {
195         socket_close( channel->fd );
196         channel->fd = -1;
197     }
198     channel->next    = _s_free_channels;
199     _s_free_channels = channel;
200 }
201 
202 
203 static void
sys_channel_read_handler(void * _channel)204 sys_channel_read_handler( void*  _channel )
205 {
206     SysChannel  channel = _channel;
207     D( "%s: read event for channel %p:%d\n", __FUNCTION__,
208        channel, channel->fd );
209     channel->callback( channel->opaque, SYS_EVENT_READ );
210 }
211 
212 static void
sys_channel_write_handler(void * _channel)213 sys_channel_write_handler( void*  _channel )
214 {
215     SysChannel  channel = _channel;
216     D( "%s: write event for channel %p:%d\n", __FUNCTION__, channel, channel->fd );
217     channel->callback( channel->opaque, SYS_EVENT_WRITE );
218 }
219 
220 void
sys_channel_on(SysChannel channel,int events,SysChannelCallback event_callback,void * event_opaque)221 sys_channel_on( SysChannel          channel,
222                 int                 events,
223                 SysChannelCallback  event_callback,
224                 void*               event_opaque )
225 {
226     IOHandler*  read_handler  = NULL;
227     IOHandler*  write_handler = NULL;
228 
229     if (events & SYS_EVENT_READ) {
230         read_handler = sys_channel_read_handler;
231     }
232     if (events & SYS_EVENT_WRITE) {
233         write_handler = sys_channel_write_handler;
234     }
235     channel->callback = event_callback;
236     channel->opaque   = event_opaque;
237     qemu_set_fd_handler( channel->fd, read_handler, write_handler, channel );
238 }
239 
240 int
sys_channel_read(SysChannel channel,void * buffer,int size)241 sys_channel_read( SysChannel  channel, void*  buffer, int  size )
242 {
243     int   len = size;
244     char* buf = (char*) buffer;
245 
246     while (len > 0) {
247         int  ret = socket_recv(channel->fd, buf, len);
248         if (ret < 0) {
249             if (errno == EINTR)
250                 continue;
251             if (errno == EWOULDBLOCK)
252                 break;
253             D( "%s: after reading %d bytes, recv() returned error %d: %s\n",
254                 __FUNCTION__, size - len, errno, errno_str);
255             return -1;
256         } else if (ret == 0) {
257             break;
258         } else {
259             buf += ret;
260             len -= ret;
261         }
262     }
263     return size - len;
264 }
265 
266 
267 int
sys_channel_write(SysChannel channel,const void * buffer,int size)268 sys_channel_write( SysChannel  channel, const void*  buffer, int  size )
269 {
270     int         len = size;
271     const char* buf = (const char*) buffer;
272 
273     while (len > 0) {
274         int  ret = socket_send(channel->fd, buf, len);
275         if (ret < 0) {
276             if (errno == EINTR)
277                 continue;
278             if (errno == EWOULDBLOCK)
279                 break;
280             D( "%s: send() returned error %d: %s\n",
281                 __FUNCTION__, errno, errno_str);
282             return -1;
283         } else if (ret == 0) {
284             break;
285         } else {
286             buf += ret;
287             len -= ret;
288         }
289     }
290     return size - len;
291 }
292 
sys_channel_close(SysChannel channel)293 void  sys_channel_close( SysChannel  channel )
294 {
295     qemu_set_fd_handler( channel->fd, NULL, NULL, NULL );
296     sys_channel_free( channel );
297 }
298 
sys_main_init(void)299 void  sys_main_init( void )
300 {
301     sys_init_channels();
302     sys_init_timers();
303 }
304 
305 
sys_main_loop(void)306 int   sys_main_loop( void )
307 {
308     /* no looping, qemu has its own event loop */
309     return 0;
310 }
311 
312 
313 
314 
315 SysChannel
sys_channel_create_tcp_server(int port)316 sys_channel_create_tcp_server( int port )
317 {
318     SysChannel  channel = sys_channel_alloc();
319 
320     channel->fd = socket_anyaddr_server( port, SOCKET_STREAM );
321     if (channel->fd < 0) {
322         D( "%s: failed to created network socket on TCP:%d\n",
323             __FUNCTION__, port );
324         sys_channel_free( channel );
325         return NULL;
326     }
327 
328     D( "%s: server channel %p:%d now listening on port %d\n",
329        __FUNCTION__, channel, channel->fd, port );
330 
331     return channel;
332 }
333 
334 
335 SysChannel
sys_channel_create_tcp_handler(SysChannel server_channel)336 sys_channel_create_tcp_handler( SysChannel  server_channel )
337 {
338     SysChannel  channel = sys_channel_alloc();
339 
340     D( "%s: creating handler from server channel %p:%d\n", __FUNCTION__,
341        server_channel, server_channel->fd );
342 
343     channel->fd = socket_accept_any( server_channel->fd );
344     if (channel->fd < 0) {
345         perror( "accept" );
346         sys_channel_free( channel );
347         return NULL;
348     }
349 
350     /* disable Nagle algorithm */
351     socket_set_nodelay( channel->fd );
352 
353     D( "%s: handler %p:%d created from server %p:%d\n", __FUNCTION__,
354         server_channel, server_channel->fd, channel, channel->fd );
355 
356      return channel;
357 }
358 
359 
360 SysChannel
sys_channel_create_tcp_client(const char * hostname,int port)361 sys_channel_create_tcp_client( const char*  hostname, int  port )
362 {
363     SysChannel  channel = sys_channel_alloc();
364 
365     channel->fd = socket_network_client( hostname, port, SOCKET_STREAM );
366     if (channel->fd < 0) {
367         sys_channel_free(channel);
368         return NULL;
369     };
370 
371     /* set to non-blocking and disable Nagle algorithm */
372     socket_set_nonblock( channel->fd );
373     socket_set_nodelay( channel->fd );
374 
375     return channel;
376 }
377 
378