• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* This file implements the 'tcp:' goldfish pipe type which allows
18  * guest clients to directly connect to a TCP port through /dev/qemu_pipe.
19  */
20 
21 #include "sockets.h"
22 #include "android/utils/assert.h"
23 #include "android/utils/panic.h"
24 #include "android/utils/system.h"
25 #include "android/async-utils.h"
26 #include "android/opengles.h"
27 #include "android/looper.h"
28 #include "hw/goldfish_pipe.h"
29 
30 /* Implement the OpenGL fast-pipe */
31 
32 /* Set to 1 or 2 for debug traces */
33 // #define  DEBUG  1
34 
35 #if DEBUG >= 1
36 #  define D(...)   printf(__VA_ARGS__), printf("\n")
37 #else
38 #  define D(...)   ((void)0)
39 #endif
40 
41 #if DEBUG >= 2
42 #  define DD(...)                       printf(__VA_ARGS__), printf("\n")
43 #  define DDASSERT(cond)                _ANDROID_ASSERT(cond, "Assertion failure: ", #cond)
44 #  define DDASSERT_INT_OP(cond,val,op)  _ANDROID_ASSERT_INT_OP(cond,val,op)
45 #else
46 #  define DD(...)                       ((void)0)
47 #  define DDASSERT(cond)                ((void)0)
48 #  define DDASSERT_INT_OP(cond,val,op)  ((void)0)
49 #endif
50 
51 #define DDASSERT_INT_LT(cond,val)  DDASSERT_INT_OP(cond,val,<)
52 #define DDASSERT_INT_LTE(cond,val)  DDASSERT_INT_OP(cond,val,<=)
53 #define DDASSERT_INT_GT(cond,val)  DDASSERT_INT_OP(cond,val,>)
54 #define DDASSERT_INT_GTE(cond,val)  DDASSERT_INT_OP(cond,val,>=)
55 #define DDASSERT_INT_EQ(cond,val)  DDASSERT_INT_OP(cond,val,==)
56 #define DDASSERT_INT_NEQ(cond,val)  DDASSERT_INT_OP(cond,val,!=)
57 
58 enum {
59     STATE_INIT,
60     STATE_CONNECTING,
61     STATE_CONNECTED,
62     STATE_CLOSING_GUEST,
63     STATE_CLOSING_SOCKET
64 };
65 
66 typedef struct {
67     void*           hwpipe;
68     int             state;
69     int             wakeWanted;
70     LoopIo          io[1];
71     AsyncConnector  connector[1];
72 } NetPipe;
73 
74 static void
netPipe_free(NetPipe * pipe)75 netPipe_free( NetPipe*  pipe )
76 {
77     int  fd;
78 
79     /* Close the socket */
80     fd = pipe->io->fd;
81     loopIo_done(pipe->io);
82     socket_close(fd);
83 
84     /* Release the pipe object */
85     AFREE(pipe);
86 }
87 
88 
89 static void
netPipe_resetState(NetPipe * pipe)90 netPipe_resetState( NetPipe* pipe )
91 {
92     if ((pipe->wakeWanted & PIPE_WAKE_WRITE) != 0) {
93         loopIo_wantWrite(pipe->io);
94     } else {
95         loopIo_dontWantWrite(pipe->io);
96     }
97 
98    if (pipe->state == STATE_CONNECTED && (pipe->wakeWanted & PIPE_WAKE_READ) != 0) {
99         loopIo_wantRead(pipe->io);
100     } else {
101         loopIo_dontWantRead(pipe->io);
102     }
103 }
104 
105 
106 /* This function is only called when the socket is disconnected.
107  * See netPipe_closeFromGuest() for the case when the guest requires
108  * the disconnection. */
109 static void
netPipe_closeFromSocket(void * opaque)110 netPipe_closeFromSocket( void* opaque )
111 {
112     NetPipe*  pipe = opaque;
113 
114     D("%s", __FUNCTION__);
115 
116     /* If the guest already ordered the pipe to be closed, delete immediately */
117     if (pipe->state == STATE_CLOSING_GUEST) {
118         netPipe_free(pipe);
119         return;
120     }
121 
122     /* Force the closure of the QEMUD channel - if a guest is blocked
123      * waiting for a wake signal, it will receive an error. */
124     if (pipe->hwpipe != NULL) {
125         goldfish_pipe_close(pipe->hwpipe);
126         pipe->hwpipe = NULL;
127     }
128 
129     pipe->state = STATE_CLOSING_SOCKET;
130     netPipe_resetState(pipe);
131 }
132 
133 
134 /* This is the function that gets called each time there is an asynchronous
135  * event on the network pipe.
136  */
137 static void
netPipe_io_func(void * opaque,int fd,unsigned events)138 netPipe_io_func( void* opaque, int fd, unsigned events )
139 {
140     NetPipe*  pipe = opaque;
141     int         wakeFlags = 0;
142 
143     /* Run the connector if we are in the CONNECTING state     */
144     /* TODO: Add some sort of time-out, to deal with the case */
145     /*        when the server is wedged.                      */
146     if (pipe->state == STATE_CONNECTING) {
147         AsyncStatus  status = asyncConnector_run(pipe->connector);
148         if (status == ASYNC_NEED_MORE) {
149             return;
150         }
151         else if (status == ASYNC_ERROR) {
152             /* Could not connect, tell our client by closing the channel. */
153 
154             netPipe_closeFromSocket(pipe);
155             return;
156         }
157         pipe->state = STATE_CONNECTED;
158         netPipe_resetState(pipe);
159         return;
160     }
161 
162     /* Otherwise, accept incoming data */
163     if ((events & LOOP_IO_READ) != 0) {
164         if ((pipe->wakeWanted & PIPE_WAKE_READ) != 0) {
165             wakeFlags |= PIPE_WAKE_READ;
166         }
167     }
168 
169     if ((events & LOOP_IO_WRITE) != 0) {
170         if ((pipe->wakeWanted & PIPE_WAKE_WRITE) != 0) {
171             wakeFlags |= PIPE_WAKE_WRITE;
172         }
173     }
174 
175     /* Send wake signal to the guest if needed */
176     if (wakeFlags != 0) {
177         goldfish_pipe_wake(pipe->hwpipe, wakeFlags);
178         pipe->wakeWanted &= ~wakeFlags;
179     }
180 
181     /* Reset state */
182     netPipe_resetState(pipe);
183 }
184 
185 
186 void*
netPipe_initFromAddress(void * hwpipe,const SockAddress * address,Looper * looper)187 netPipe_initFromAddress( void* hwpipe, const SockAddress*  address, Looper* looper )
188 {
189     NetPipe*     pipe;
190 
191     ANEW0(pipe);
192 
193     pipe->hwpipe = hwpipe;
194     pipe->state  = STATE_INIT;
195 
196     {
197         AsyncStatus  status;
198 
199         int  fd = socket_create( sock_address_get_family(address), SOCKET_STREAM );
200         if (fd < 0) {
201             D("%s: Could create socket from address family!", __FUNCTION__);
202             netPipe_free(pipe);
203             return NULL;
204         }
205 
206         loopIo_init(pipe->io, looper, fd, netPipe_io_func, pipe);
207         status = asyncConnector_init(pipe->connector, address, pipe->io);
208         pipe->state = STATE_CONNECTING;
209 
210         if (status == ASYNC_ERROR) {
211             D("%s: Could not connect to socket: %s",
212               __FUNCTION__, errno_str);
213             netPipe_free(pipe);
214             return NULL;
215         }
216         if (status == ASYNC_COMPLETE) {
217             pipe->state = STATE_CONNECTED;
218             netPipe_resetState(pipe);
219         }
220     }
221 
222     return pipe;
223 }
224 
225 
226 /* Called when the guest wants to close the channel. This is different
227  * from netPipe_closeFromSocket() which is called when the socket is
228  * disconnected. */
229 static void
netPipe_closeFromGuest(void * opaque)230 netPipe_closeFromGuest( void* opaque )
231 {
232     NetPipe*  pipe = opaque;
233     netPipe_free(pipe);
234 }
235 
netPipeReadySend(NetPipe * pipe)236 static int netPipeReadySend(NetPipe *pipe)
237 {
238     if (pipe->state == STATE_CONNECTED)
239         return 0;
240     else if (pipe->state == STATE_CONNECTING)
241         return PIPE_ERROR_AGAIN;
242     else if (pipe->hwpipe == NULL)
243         return PIPE_ERROR_INVAL;
244     else
245         return PIPE_ERROR_IO;
246 }
247 
248 static int
netPipe_sendBuffers(void * opaque,const GoldfishPipeBuffer * buffers,int numBuffers)249 netPipe_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers )
250 {
251     NetPipe*  pipe = opaque;
252     int       count = 0;
253     int       ret   = 0;
254     int       buffStart = 0;
255     const GoldfishPipeBuffer* buff = buffers;
256     const GoldfishPipeBuffer* buffEnd = buff + numBuffers;
257 
258     ret = netPipeReadySend(pipe);
259     if (ret != 0)
260         return ret;
261 
262     for (; buff < buffEnd; buff++)
263         count += buff->size;
264 
265     buff = buffers;
266     while (count > 0) {
267         int  avail = buff->size - buffStart;
268         int  len = socket_send(pipe->io->fd, buff->data + buffStart, avail);
269 
270         /* the write succeeded */
271         if (len > 0) {
272             buffStart += len;
273             if (buffStart >= buff->size) {
274                 buff++;
275                 buffStart = 0;
276             }
277             count -= len;
278             ret   += len;
279             continue;
280         }
281 
282         /* we reached the end of stream? */
283         if (len == 0) {
284             if (ret == 0)
285                 ret = PIPE_ERROR_IO;
286             break;
287         }
288 
289         /* if we already wrote some stuff, simply return */
290         if (ret > 0) {
291             break;
292         }
293 
294         /* need to return an appropriate error code */
295         if (errno == EAGAIN || errno == EWOULDBLOCK) {
296             ret = PIPE_ERROR_AGAIN;
297         } else {
298             ret = PIPE_ERROR_IO;
299         }
300         break;
301     }
302 
303     return ret;
304 }
305 
306 static int
netPipe_recvBuffers(void * opaque,GoldfishPipeBuffer * buffers,int numBuffers)307 netPipe_recvBuffers( void* opaque, GoldfishPipeBuffer*  buffers, int  numBuffers )
308 {
309     NetPipe*  pipe = opaque;
310     int       count = 0;
311     int       ret   = 0;
312     int       buffStart = 0;
313     GoldfishPipeBuffer* buff = buffers;
314     GoldfishPipeBuffer* buffEnd = buff + numBuffers;
315 
316     for (; buff < buffEnd; buff++)
317         count += buff->size;
318 
319     buff = buffers;
320     while (count > 0) {
321         int  avail = buff->size - buffStart;
322         int  len = socket_recv(pipe->io->fd, buff->data + buffStart, avail);
323 
324         /* the read succeeded */
325         if (len > 0) {
326             buffStart += len;
327             if (buffStart >= buff->size) {
328                 buff++;
329                 buffStart = 0;
330             }
331             count -= len;
332             ret   += len;
333             continue;
334         }
335 
336         /* we reached the end of stream? */
337         if (len == 0) {
338             if (ret == 0)
339                 ret = PIPE_ERROR_IO;
340             break;
341         }
342 
343         /* if we already read some stuff, simply return */
344         if (ret > 0) {
345             break;
346         }
347 
348         /* need to return an appropriate error code */
349         if (errno == EAGAIN || errno == EWOULDBLOCK) {
350             ret = PIPE_ERROR_AGAIN;
351         } else {
352             ret = PIPE_ERROR_IO;
353         }
354         break;
355     }
356     return ret;
357 }
358 
359 static unsigned
netPipe_poll(void * opaque)360 netPipe_poll( void* opaque )
361 {
362     NetPipe*  pipe = opaque;
363     unsigned  mask = loopIo_poll(pipe->io);
364     unsigned  ret  = 0;
365 
366     if (mask & LOOP_IO_READ)
367         ret |= PIPE_POLL_IN;
368     if (mask & LOOP_IO_WRITE)
369         ret |= PIPE_POLL_OUT;
370 
371     return ret;
372 }
373 
374 static void
netPipe_wakeOn(void * opaque,int flags)375 netPipe_wakeOn( void* opaque, int flags )
376 {
377     NetPipe*  pipe = opaque;
378 
379     DD("%s: flags=%d", __FUNCTION__, flags);
380 
381     pipe->wakeWanted |= flags;
382     netPipe_resetState(pipe);
383 }
384 
385 
386 void*
netPipe_initTcp(void * hwpipe,void * _looper,const char * args)387 netPipe_initTcp( void* hwpipe, void* _looper, const char* args )
388 {
389     /* Build SockAddress from arguments. Acceptable formats are:
390      *   <port>
391      */
392     SockAddress  address;
393     uint16_t     port;
394     void*        ret;
395 
396     if (args == NULL) {
397         D("%s: Missing address!", __FUNCTION__);
398         return NULL;
399     }
400     D("%s: Port is '%s'", __FUNCTION__, args);
401 
402     /* Now, look at the port number */
403     {
404         char* end;
405         long  val = strtol(args, &end, 10);
406         if (end == NULL || *end != '\0' || val <= 0 || val > 65535) {
407             D("%s: Invalid port number: '%s'", __FUNCTION__, args);
408         }
409         port = (uint16_t)val;
410     }
411     sock_address_init_inet(&address, SOCK_ADDRESS_INET_LOOPBACK, port);
412 
413     ret = netPipe_initFromAddress(hwpipe, &address, _looper);
414 
415     sock_address_done(&address);
416     return ret;
417 }
418 
419 #ifndef _WIN32
420 void*
netPipe_initUnix(void * hwpipe,void * _looper,const char * args)421 netPipe_initUnix( void* hwpipe, void* _looper, const char* args )
422 {
423     /* Build SockAddress from arguments. Acceptable formats are:
424      *
425      *   <path>
426      */
427     SockAddress  address;
428     void*        ret;
429 
430     if (args == NULL || args[0] == '\0') {
431         D("%s: Missing address!", __FUNCTION__);
432         return NULL;
433     }
434     D("%s: Address is '%s'", __FUNCTION__, args);
435 
436     sock_address_init_unix(&address, args);
437 
438     ret = netPipe_initFromAddress(hwpipe, &address, _looper);
439 
440     sock_address_done(&address);
441     return ret;
442 }
443 #endif
444 
445 /**********************************************************************
446  **********************************************************************
447  *****
448  *****  N E T W O R K   P I P E   M E S S A G E S
449  *****
450  *****/
451 
452 static const GoldfishPipeFuncs  netPipeTcp_funcs = {
453     netPipe_initTcp,
454     netPipe_closeFromGuest,
455     netPipe_sendBuffers,
456     netPipe_recvBuffers,
457     netPipe_poll,
458     netPipe_wakeOn,
459     NULL,  /* we can't save these */
460     NULL,  /* we can't load these */
461 };
462 
463 #ifndef _WIN32
464 static const GoldfishPipeFuncs  netPipeUnix_funcs = {
465     netPipe_initUnix,
466     netPipe_closeFromGuest,
467     netPipe_sendBuffers,
468     netPipe_recvBuffers,
469     netPipe_poll,
470     netPipe_wakeOn,
471     NULL,  /* we can't save these */
472     NULL,  /* we can't load these */
473 };
474 #endif
475 
476 /* This is set to 1 in android_init_opengles() below, and tested
477  * by openglesPipe_init() to refuse a pipe connection if the function
478  * was never called.
479  */
480 static int  _opengles_init;
481 
482 static void*
openglesPipe_init(void * hwpipe,void * _looper,const char * args)483 openglesPipe_init( void* hwpipe, void* _looper, const char* args )
484 {
485     char temp[32];
486     NetPipe *pipe;
487 
488     if (!_opengles_init) {
489         /* This should never happen, unless there is a bug in the
490          * emulator's initialization, or the system image. */
491         D("Trying to open the OpenGLES pipe without GPU emulation!");
492         return NULL;
493     }
494 
495     char server_addr[PATH_MAX];
496     android_gles_server_path(server_addr, sizeof(server_addr));
497 #ifndef _WIN32
498     if (android_gles_fast_pipes) {
499         pipe = (NetPipe *)netPipe_initUnix(hwpipe, _looper, server_addr);
500         D("Creating Unix OpenGLES pipe for GPU emulation: %s", server_addr);
501     } else {
502 #else /* _WIN32 */
503     {
504 #endif
505         /* Connect through TCP as a fallback */
506         pipe = (NetPipe *)netPipe_initTcp(hwpipe, _looper, server_addr);
507         D("Creating TCP OpenGLES pipe for GPU emulation!");
508     }
509     if (pipe != NULL) {
510         // Disable TCP nagle algorithm to improve throughput of small packets
511         socket_set_nodelay(pipe->io->fd);
512 
513     // On Win32, adjust buffer sizes
514 #ifdef _WIN32
515         {
516             int sndbuf = 128 * 1024;
517             int len = sizeof(sndbuf);
518             if (setsockopt(pipe->io->fd, SOL_SOCKET, SO_SNDBUF,
519                         (char*)&sndbuf, len) == SOCKET_ERROR) {
520                 D("Failed to set SO_SNDBUF to %d error=0x%x\n",
521                 sndbuf, WSAGetLastError());
522             }
523         }
524 #endif /* _WIN32 */
525     }
526 
527     return pipe;
528 }
529 
530 static const GoldfishPipeFuncs  openglesPipe_funcs = {
531     openglesPipe_init,
532     netPipe_closeFromGuest,
533     netPipe_sendBuffers,
534     netPipe_recvBuffers,
535     netPipe_poll,
536     netPipe_wakeOn,
537     NULL,  /* we can't save these */
538     NULL,  /* we can't load these */
539 };
540 
541 void
542 android_net_pipes_init(void)
543 {
544     Looper*  looper = looper_newCore();
545 
546     goldfish_pipe_add_type( "tcp", looper, &netPipeTcp_funcs );
547 #ifndef _WIN32
548     goldfish_pipe_add_type( "unix", looper, &netPipeUnix_funcs );
549 #endif
550     goldfish_pipe_add_type( "opengles", looper, &openglesPipe_funcs );
551 }
552 
553 int
554 android_init_opengles_pipes(void)
555 {
556     /* TODO: Check that we can load and initialize the host emulation
557      *        libraries, and return -1 in case of error.
558      */
559     _opengles_init = 1;
560     return 0;
561 }
562