Home | History | Annotate | Download | only in android
      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
     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
     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
    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
    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*
    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
    231 netPipe_closeFromGuest( void* opaque )
    232 {
    233     NetPipe*  pipe = opaque;
    234     netPipe_free(pipe);
    235 }
    236 
    237 
    238 static int
    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
    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
    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
    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*
    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*
    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*
    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