• 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         asyncConnector_init(pipe->connector, address, pipe->io);
208         pipe->state = STATE_CONNECTING;
209 
210         status = asyncConnector_run(pipe->connector);
211         if (status == ASYNC_ERROR) {
212             D("%s: Could not connect to socket: %s",
213               __FUNCTION__, errno_str);
214             netPipe_free(pipe);
215             return NULL;
216         }
217         if (status == ASYNC_COMPLETE) {
218             pipe->state = STATE_CONNECTED;
219             netPipe_resetState(pipe);
220         }
221     }
222 
223     return pipe;
224 }
225 
226 
227 /* Called when the guest wants to close the channel. This is different
228  * from netPipe_closeFromSocket() which is called when the socket is
229  * disconnected. */
230 static void
netPipe_closeFromGuest(void * opaque)231 netPipe_closeFromGuest( void* opaque )
232 {
233     NetPipe*  pipe = opaque;
234     netPipe_free(pipe);
235 }
236 
237 
238 static int
netPipe_sendBuffers(void * opaque,const GoldfishPipeBuffer * buffers,int numBuffers)239 netPipe_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers )
240 {
241     NetPipe*  pipe = opaque;
242     int       count = 0;
243     int       ret   = 0;
244     int       buffStart = 0;
245     const GoldfishPipeBuffer* buff = buffers;
246     const GoldfishPipeBuffer* buffEnd = buff + numBuffers;
247 
248     for (; buff < buffEnd; buff++)
249         count += buff->size;
250 
251     buff = buffers;
252     while (count > 0) {
253         int  avail = buff->size - buffStart;
254         int  len = socket_send(pipe->io->fd, buff->data + buffStart, avail);
255 
256         /* the write succeeded */
257         if (len > 0) {
258             buffStart += len;
259             if (buffStart >= buff->size) {
260                 buff++;
261                 buffStart = 0;
262             }
263             count -= len;
264             ret   += len;
265             continue;
266         }
267 
268         /* we reached the end of stream? */
269         if (len == 0) {
270             if (ret == 0)
271                 ret = PIPE_ERROR_IO;
272             break;
273         }
274 
275         /* if we already wrote some stuff, simply return */
276         if (ret > 0) {
277             break;
278         }
279 
280         /* need to return an appropriate error code */
281         if (errno == EAGAIN || errno == EWOULDBLOCK) {
282             ret = PIPE_ERROR_AGAIN;
283         } else {
284             ret = PIPE_ERROR_IO;
285         }
286         break;
287     }
288 
289     return ret;
290 }
291 
292 static int
netPipe_recvBuffers(void * opaque,GoldfishPipeBuffer * buffers,int numBuffers)293 netPipe_recvBuffers( void* opaque, GoldfishPipeBuffer*  buffers, int  numBuffers )
294 {
295     NetPipe*  pipe = opaque;
296     int       count = 0;
297     int       ret   = 0;
298     int       buffStart = 0;
299     GoldfishPipeBuffer* buff = buffers;
300     GoldfishPipeBuffer* buffEnd = buff + numBuffers;
301 
302     for (; buff < buffEnd; buff++)
303         count += buff->size;
304 
305     buff = buffers;
306     while (count > 0) {
307         int  avail = buff->size - buffStart;
308         int  len = socket_recv(pipe->io->fd, buff->data + buffStart, avail);
309 
310         /* the read succeeded */
311         if (len > 0) {
312             buffStart += len;
313             if (buffStart >= buff->size) {
314                 buff++;
315                 buffStart = 0;
316             }
317             count -= len;
318             ret   += len;
319             continue;
320         }
321 
322         /* we reached the end of stream? */
323         if (len == 0) {
324             if (ret == 0)
325                 ret = PIPE_ERROR_IO;
326             break;
327         }
328 
329         /* if we already read some stuff, simply return */
330         if (ret > 0) {
331             break;
332         }
333 
334         /* need to return an appropriate error code */
335         if (errno == EAGAIN || errno == EWOULDBLOCK) {
336             ret = PIPE_ERROR_AGAIN;
337         } else {
338             ret = PIPE_ERROR_IO;
339         }
340         break;
341     }
342     return ret;
343 }
344 
345 static unsigned
netPipe_poll(void * opaque)346 netPipe_poll( void* opaque )
347 {
348     NetPipe*  pipe = opaque;
349     unsigned  mask = loopIo_poll(pipe->io);
350     unsigned  ret  = 0;
351 
352     if (mask & LOOP_IO_READ)
353         ret |= PIPE_POLL_IN;
354     if (mask & LOOP_IO_WRITE)
355         ret |= PIPE_POLL_OUT;
356 
357     return ret;
358 }
359 
360 static void
netPipe_wakeOn(void * opaque,int flags)361 netPipe_wakeOn( void* opaque, int flags )
362 {
363     NetPipe*  pipe = opaque;
364 
365     DD("%s: flags=%d", __FUNCTION__, flags);
366 
367     pipe->wakeWanted |= flags;
368     netPipe_resetState(pipe);
369 }
370 
371 
372 void*
netPipe_initTcp(void * hwpipe,void * _looper,const char * args)373 netPipe_initTcp( void* hwpipe, void* _looper, const char* args )
374 {
375     /* Build SockAddress from arguments. Acceptable formats are:
376      *   <port>
377      */
378     SockAddress  address;
379     uint16_t     port;
380     void*        ret;
381 
382     if (args == NULL) {
383         D("%s: Missing address!", __FUNCTION__);
384         return NULL;
385     }
386     D("%s: Port is '%s'", __FUNCTION__, args);
387 
388     /* Now, look at the port number */
389     {
390         char* end;
391         long  val = strtol(args, &end, 10);
392         if (end == NULL || *end != '\0' || val <= 0 || val > 65535) {
393             D("%s: Invalid port number: '%s'", __FUNCTION__, args);
394         }
395         port = (uint16_t)val;
396     }
397     sock_address_init_inet(&address, SOCK_ADDRESS_INET_LOOPBACK, port);
398 
399     ret = netPipe_initFromAddress(hwpipe, &address, _looper);
400 
401     sock_address_done(&address);
402     return ret;
403 }
404 
405 #ifndef _WIN32
406 void*
netPipe_initUnix(void * hwpipe,void * _looper,const char * args)407 netPipe_initUnix( void* hwpipe, void* _looper, const char* args )
408 {
409     /* Build SockAddress from arguments. Acceptable formats are:
410      *
411      *   <path>
412      */
413     SockAddress  address;
414     void*        ret;
415 
416     if (args == NULL || args[0] == '\0') {
417         D("%s: Missing address!", __FUNCTION__);
418         return NULL;
419     }
420     D("%s: Address is '%s'", __FUNCTION__, args);
421 
422     sock_address_init_unix(&address, args);
423 
424     ret = netPipe_initFromAddress(hwpipe, &address, _looper);
425 
426     sock_address_done(&address);
427     return ret;
428 }
429 #endif
430 
431 /**********************************************************************
432  **********************************************************************
433  *****
434  *****  N E T W O R K   P I P E   M E S S A G E S
435  *****
436  *****/
437 
438 static const GoldfishPipeFuncs  netPipeTcp_funcs = {
439     netPipe_initTcp,
440     netPipe_closeFromGuest,
441     netPipe_sendBuffers,
442     netPipe_recvBuffers,
443     netPipe_poll,
444     netPipe_wakeOn,
445     NULL,  /* we can't save these */
446     NULL,  /* we can't load these */
447 };
448 
449 #ifndef _WIN32
450 static const GoldfishPipeFuncs  netPipeUnix_funcs = {
451     netPipe_initUnix,
452     netPipe_closeFromGuest,
453     netPipe_sendBuffers,
454     netPipe_recvBuffers,
455     netPipe_poll,
456     netPipe_wakeOn,
457     NULL,  /* we can't save these */
458     NULL,  /* we can't load these */
459 };
460 #endif
461 
462 /* This is set to 1 in android_init_opengles() below, and tested
463  * by openglesPipe_init() to refuse a pipe connection if the function
464  * was never called.
465  */
466 static int  _opengles_init;
467 
468 static void*
openglesPipe_init(void * hwpipe,void * _looper,const char * args)469 openglesPipe_init( void* hwpipe, void* _looper, const char* args )
470 {
471     char temp[32];
472     NetPipe *pipe;
473 
474     if (!_opengles_init) {
475         /* This should never happen, unless there is a bug in the
476          * emulator's initialization, or the system image. */
477         D("Trying to open the OpenGLES pipe without GPU emulation!");
478         return NULL;
479     }
480 
481 #ifndef _WIN32
482     if (android_gles_fast_pipes) {
483         char  unix_path[PATH_MAX];
484         android_gles_unix_path(unix_path, sizeof(unix_path), ANDROID_OPENGLES_BASE_PORT);
485         pipe = (NetPipe *)netPipe_initUnix(hwpipe, _looper, unix_path);
486         D("Creating Unix OpenGLES pipe for GPU emulation: %s", unix_path);
487     } else {
488 #else /* _WIN32 */
489     {
490 #endif
491         /* Connect through TCP as a fallback */
492         snprintf(temp, sizeof temp, "%d", ANDROID_OPENGLES_BASE_PORT);
493         pipe = (NetPipe *)netPipe_initTcp(hwpipe, _looper, temp);
494         D("Creating TCP OpenGLES pipe for GPU emulation!");
495     }
496     if (pipe != NULL) {
497         // Disable TCP nagle algorithm to improve throughput of small packets
498         socket_set_nodelay(pipe->io->fd);
499 
500     // On Win32, adjust buffer sizes
501 #ifdef _WIN32
502         {
503             int sndbuf = 128 * 1024;
504             int len = sizeof(sndbuf);
505             if (setsockopt(pipe->io->fd, SOL_SOCKET, SO_SNDBUF,
506                         (char*)&sndbuf, len) == SOCKET_ERROR) {
507                 D("Failed to set SO_SNDBUF to %d error=0x%x\n",
508                 sndbuf, WSAGetLastError());
509             }
510         }
511 #endif /* _WIN32 */
512     }
513 
514     return pipe;
515 }
516 
517 static const GoldfishPipeFuncs  openglesPipe_funcs = {
518     openglesPipe_init,
519     netPipe_closeFromGuest,
520     netPipe_sendBuffers,
521     netPipe_recvBuffers,
522     netPipe_poll,
523     netPipe_wakeOn,
524     NULL,  /* we can't save these */
525     NULL,  /* we can't load these */
526 };
527 
528 void
529 android_net_pipes_init(void)
530 {
531     Looper*  looper = looper_newCore();
532 
533     goldfish_pipe_add_type( "tcp", looper, &netPipeTcp_funcs );
534 #ifndef _WIN32
535     goldfish_pipe_add_type( "unix", looper, &netPipeUnix_funcs );
536 #endif
537     goldfish_pipe_add_type( "opengles", looper, &openglesPipe_funcs );
538 }
539 
540 int
541 android_init_opengles_pipes(void)
542 {
543     /* TODO: Check that we can load and initialize the host emulation
544      *        libraries, and return -1 in case of error.
545      */
546     _opengles_init = 1;
547     return 0;
548 }
549