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