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