hw-pipe-net.c revision afe299d6284ecb86ba5c073d2c969aedd86597db
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/looper.h"
27#include "hw/goldfish_pipe.h"
28
29/* Implement the OpenGL fast-pipe */
30
31/* Set to 1 or 2 for debug traces */
32#define  DEBUG  1
33
34#if DEBUG >= 1
35#  define D(...)   printf(__VA_ARGS__), printf("\n")
36#else
37#  define D(...)   ((void)0)
38#endif
39
40#if DEBUG >= 2
41#  define DD(...)                       printf(__VA_ARGS__), printf("\n")
42#  define DDASSERT(cond)                _ANDROID_ASSERT(cond, "Assertion failure: ", #cond)
43#  define DDASSERT_INT_OP(cond,val,op)  _ANDROID_ASSERT_INT_OP(cond,val,op)
44#else
45#  define DD(...)                       ((void)0)
46#  define DDASSERT(cond)                ((void)0)
47#  define DDASSERT_INT_OP(cond,val,op)  ((void)0)
48#endif
49
50#define DDASSERT_INT_LT(cond,val)  DDASSERT_INT_OP(cond,val,<)
51#define DDASSERT_INT_LTE(cond,val)  DDASSERT_INT_OP(cond,val,<=)
52#define DDASSERT_INT_GT(cond,val)  DDASSERT_INT_OP(cond,val,>)
53#define DDASSERT_INT_GTE(cond,val)  DDASSERT_INT_OP(cond,val,>=)
54#define DDASSERT_INT_EQ(cond,val)  DDASSERT_INT_OP(cond,val,==)
55#define DDASSERT_INT_NEQ(cond,val)  DDASSERT_INT_OP(cond,val,!=)
56
57enum {
58    STATE_INIT,
59    STATE_CONNECTING,
60    STATE_CONNECTED,
61    STATE_CLOSING_GUEST,
62    STATE_CLOSING_SOCKET
63};
64
65typedef struct {
66    void*           hwpipe;
67    int             state;
68    int             wakeWanted;
69    LoopIo          io[1];
70    AsyncConnector  connector[1];
71
72} NetPipe;
73
74static void
75netPipe_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
89static void
90netPipe_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. */
109static void
110netPipe_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 */
137static void
138netPipe_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
186void*
187netPipe_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. */
230static void
231netPipe_closeFromGuest( void* opaque )
232{
233    NetPipe*  pipe = opaque;
234    netPipe_free(pipe);
235}
236
237
238static int
239netPipe_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
292static int
293netPipe_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
345static unsigned
346netPipe_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_WAKE_READ;
354    if (mask & LOOP_IO_WRITE)
355        ret |= PIPE_WAKE_WRITE;
356
357    return ret;
358}
359
360static void
361netPipe_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
372void*
373netPipe_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
406void*
407netPipe_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
438static const GoldfishPipeFuncs  netPipeTcp_funcs = {
439    netPipe_initTcp,
440    netPipe_closeFromGuest,
441    netPipe_sendBuffers,
442    netPipe_recvBuffers,
443    netPipe_poll,
444    netPipe_wakeOn,
445};
446
447#ifndef _WIN32
448static const GoldfishPipeFuncs  netPipeUnix_funcs = {
449    netPipe_initUnix,
450    netPipe_closeFromGuest,
451    netPipe_sendBuffers,
452    netPipe_recvBuffers,
453    netPipe_poll,
454    netPipe_wakeOn,
455};
456#endif
457
458#define DEFAULT_OPENGLES_PORT  22468
459
460static void*
461openglesPipe_init( void* hwpipe, void* _looper, const char* args )
462{
463    char temp[32];
464
465    /* For now, simply connect through tcp */
466    snprintf(temp, sizeof temp, "%d", DEFAULT_OPENGLES_PORT);
467    return netPipe_initTcp(hwpipe, _looper, temp);
468}
469
470static const GoldfishPipeFuncs  openglesPipe_funcs = {
471    openglesPipe_init,
472    netPipe_closeFromGuest,
473    netPipe_sendBuffers,
474    netPipe_recvBuffers,
475    netPipe_poll,
476    netPipe_wakeOn,
477};
478
479
480void
481android_net_pipes_init(void)
482{
483    Looper*  looper = looper_newCore();
484
485    goldfish_pipe_add_type( "tcp", looper, &netPipeTcp_funcs );
486#ifndef _WIN32
487    goldfish_pipe_add_type( "unix", looper, &netPipeUnix_funcs );
488#endif
489    goldfish_pipe_add_type( "opengles", looper, &openglesPipe_funcs );
490}
491