1 // 2 // Copyright 2005 The Android Open Source Project 3 // 4 // Local named bi-directional communication channel. 5 // 6 #include "LocalBiChannel.h" 7 #include "utils/Log.h" 8 9 #if defined(HAVE_WIN32_IPC) 10 # define _WIN32_WINNT 0x0500 11 # include <windows.h> 12 #else 13 # include <sys/types.h> 14 # include <sys/socket.h> 15 # include <sys/stat.h> 16 # include <sys/un.h> 17 #endif 18 19 #include <stdlib.h> 20 #include <unistd.h> 21 #include <string.h> 22 #include <errno.h> 23 #include <assert.h> 24 25 #ifndef SUN_LEN 26 /* 27 * Our current set of ARM header files don't define this. 28 */ 29 # define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ 30 + strlen ((ptr)->sun_path)) 31 #endif 32 33 using namespace android; 34 35 const unsigned long kInvalidHandle = (unsigned long) -1; 36 37 /* 38 * Initialize data fields. 39 */ 40 LocalBiChannel::LocalBiChannel(void) 41 : mFileName(NULL), mIsListener(false), mHandle(kInvalidHandle) 42 { 43 } 44 45 #if defined(HAVE_WIN32_IPC) 46 /* 47 * Implementation for Win32, using named pipes. 48 * 49 * Cygwin actually supports UNIX-domain sockets, but we want to stuff 50 * the file handles into a Pipe, which uses HANDLE under Win32. 51 */ 52 53 const int kPipeSize = 4096; 54 55 /* 56 * Destructor. If we're the server side, we may need to clean up after 57 * ourselves. 58 */ 59 LocalBiChannel::~LocalBiChannel(void) 60 { 61 if (mHandle != kInvalidHandle) 62 CloseHandle((HANDLE)mHandle); 63 64 delete[] mFileName; 65 } 66 67 /* 68 * Construct the full path. The caller must delete[] the return value. 69 */ 70 static char* makeFilename(const char* name) 71 { 72 static const char* kBasePath = "\\\\.\\pipe\\android-"; 73 char* fileName; 74 75 assert(name != NULL && name[0] != '\0'); 76 77 fileName = new char[strlen(kBasePath) + strlen(name) + 1]; 78 strcpy(fileName, kBasePath); 79 strcat(fileName, name); 80 81 return fileName; 82 } 83 84 /* 85 * Create a named pipe, so the client has something to connect to. 86 */ 87 bool LocalBiChannel::create(const char* name) 88 { 89 delete[] mFileName; 90 mFileName = makeFilename(name); 91 92 #if 0 93 HANDLE hPipe; 94 95 hPipe = CreateNamedPipe( 96 mFileName, // unique pipe name 97 PIPE_ACCESS_DUPLEX | // open mode 98 FILE_FLAG_FIRST_PIPE_INSTANCE, 99 0, // pipe mode (byte, blocking) 100 1, // max instances 101 kPipeSize, // output buffer 102 kPipeSize, // input buffer 103 NMPWAIT_USE_DEFAULT_WAIT, // client time-out 104 NULL); // security 105 106 if (hPipe == 0) { 107 LOG(LOG_ERROR, "lbicomm", 108 "CreateNamedPipe failed (err=%ld)\n", GetLastError()); 109 return false; 110 } 111 112 mHandle = (unsigned long) hPipe; 113 #endif 114 115 return true; 116 } 117 118 /* 119 * Attach to an existing named pipe. 120 */ 121 bool LocalBiChannel::attach(const char* name, Pipe** ppReadPipe, 122 Pipe** ppWritePipe) 123 { 124 HANDLE hPipe, dupHandle; 125 126 delete[] mFileName; 127 mFileName = makeFilename(name); 128 129 hPipe = CreateFile( 130 mFileName, // filename 131 GENERIC_READ | GENERIC_WRITE, // access 132 0, // no sharing 133 NULL, // security 134 OPEN_EXISTING, // don't create 135 0, // attributes 136 NULL); // template 137 if (hPipe == INVALID_HANDLE_VALUE) { 138 LOG(LOG_ERROR, "lbicomm", 139 "CreateFile on pipe '%s' failed (err=%ld)\n", name, GetLastError()); 140 return false; 141 } 142 143 assert(mHandle == kInvalidHandle); 144 145 /* 146 * Set up the pipes. Use the new handle for one, and a duplicate 147 * of it for the other, in case we decide to only close one side. 148 */ 149 *ppReadPipe = new Pipe(); 150 (*ppReadPipe)->createReader((unsigned long) hPipe); 151 152 DuplicateHandle( 153 GetCurrentProcess(), 154 hPipe, 155 GetCurrentProcess(), 156 &dupHandle, 157 0, 158 FALSE, 159 DUPLICATE_SAME_ACCESS); 160 *ppWritePipe = new Pipe(); 161 (*ppWritePipe)->createWriter((unsigned long) dupHandle); 162 163 return true; 164 } 165 166 /* 167 * Listen for a new connection, discarding any existing connection. 168 */ 169 bool LocalBiChannel::listen(Pipe** ppReadPipe, Pipe** ppWritePipe) 170 { 171 BOOL connected; 172 HANDLE hPipe; 173 174 /* 175 * Create up to 3 instances of the named pipe: 176 * - currently active connection 177 * - connection currently being rejected because one is already active 178 * - a new listener to wait for the next round 179 */ 180 hPipe = CreateNamedPipe( 181 mFileName, // unique pipe name 182 PIPE_ACCESS_DUPLEX // open mode 183 /*| FILE_FLAG_FIRST_PIPE_INSTANCE*/, 184 0, // pipe mode (byte, blocking) 185 3, // max instances 186 kPipeSize, // output buffer 187 kPipeSize, // input buffer 188 NMPWAIT_USE_DEFAULT_WAIT, // client time-out 189 NULL); // security 190 191 if (hPipe == 0) { 192 LOG(LOG_ERROR, "lbicomm", 193 "CreateNamedPipe failed (err=%ld)\n", GetLastError()); 194 return false; 195 } 196 197 /* 198 * If a client is already connected to us, this fails with 199 * ERROR_PIPE_CONNECTED. It returns success if we had to wait 200 * a little bit before the connection happens. 201 */ 202 connected = ConnectNamedPipe(hPipe, NULL) ? 203 TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 204 205 if (connected) { 206 /* 207 * Create the pipes. Give one a duplicated handle so that, 208 * when one closes, we don't lose both. 209 */ 210 HANDLE dupHandle; 211 212 *ppReadPipe = new Pipe(); 213 (*ppReadPipe)->createReader((unsigned long) hPipe); 214 215 DuplicateHandle( 216 GetCurrentProcess(), 217 hPipe, 218 GetCurrentProcess(), 219 &dupHandle, 220 0, 221 FALSE, 222 DUPLICATE_SAME_ACCESS); 223 *ppWritePipe = new Pipe(); 224 (*ppWritePipe)->createWriter((unsigned long) dupHandle); 225 226 return true; 227 } else { 228 LOG(LOG_WARN, "lbicomm", 229 "ConnectNamedPipe failed (err=%ld)\n", GetLastError()); 230 #ifdef HAVE_WIN32_THREADS 231 Sleep(500); /* 500 ms */ 232 #else 233 usleep(500000); // DEBUG DEBUG 234 #endif 235 return false; 236 } 237 } 238 239 #else 240 241 /* 242 * Implementation for Linux and Darwin, using UNIX-domain sockets. 243 */ 244 245 /* 246 * Destructor. If we're the server side, blow away the socket file. 247 */ 248 LocalBiChannel::~LocalBiChannel(void) 249 { 250 if (mHandle != kInvalidHandle) 251 close((int) mHandle); 252 253 if (mIsListener && mFileName != NULL) { 254 LOG(LOG_DEBUG, "lbicomm", "Removing '%s'\n", mFileName); 255 (void) unlink(mFileName); 256 } 257 delete[] mFileName; 258 } 259 260 /* 261 * Construct the full path. The caller must delete[] the return value. 262 */ 263 static char* makeFilename(const char* name) 264 { 265 static const char* kBasePath = "/tmp/android-"; 266 char* fileName; 267 268 assert(name != NULL && name[0] != '\0'); 269 270 fileName = new char[strlen(kBasePath) + strlen(name) + 1]; 271 strcpy(fileName, kBasePath); 272 strcat(fileName, name); 273 274 return fileName; 275 } 276 277 /* 278 * Create a UNIX domain socket, carefully removing it if it already 279 * exists. 280 */ 281 bool LocalBiChannel::create(const char* name) 282 { 283 struct stat sb; 284 bool result = false; 285 int sock = -1; 286 int cc; 287 288 delete[] mFileName; 289 mFileName = makeFilename(name); 290 291 cc = stat(mFileName, &sb); 292 if (cc < 0) { 293 if (errno != ENOENT) { 294 LOG(LOG_ERROR, "lbicomm", 295 "Unable to stat '%s' (errno=%d)\n", mFileName, errno); 296 goto bail; 297 } 298 } else { 299 /* don't touch it if it's not a socket */ 300 if (!(S_ISSOCK(sb.st_mode))) { 301 LOG(LOG_ERROR, "lbicomm", 302 "File '%s' exists and is not a socket\n", mFileName); 303 goto bail; 304 } 305 306 /* remove the cruft */ 307 if (unlink(mFileName) < 0) { 308 LOG(LOG_ERROR, "lbicomm", 309 "Unable to remove '%s' (errno=%d)\n", mFileName, errno); 310 goto bail; 311 } 312 } 313 314 struct sockaddr_un addr; 315 316 sock = ::socket(AF_UNIX, SOCK_STREAM, 0); 317 if (sock < 0) { 318 LOG(LOG_ERROR, "lbicomm", 319 "UNIX domain socket create failed (errno=%d)\n", errno); 320 goto bail; 321 } 322 323 /* bind the socket; this creates the file on disk */ 324 strcpy(addr.sun_path, mFileName); // max 108 bytes 325 addr.sun_family = AF_UNIX; 326 cc = ::bind(sock, (struct sockaddr*) &addr, SUN_LEN(&addr)); 327 if (cc < 0) { 328 LOG(LOG_ERROR, "lbicomm", 329 "AF_UNIX bind failed for '%s' (errno=%d)\n", mFileName, errno); 330 goto bail; 331 } 332 333 mHandle = (unsigned long) sock; 334 sock = -1; 335 mIsListener = true; 336 result = true; 337 338 bail: 339 if (sock >= 0) 340 close(sock); 341 return result; 342 } 343 344 /* 345 * Attach to an existing UNIX domain socket. 346 */ 347 bool LocalBiChannel::attach(const char* name, Pipe** ppReadPipe, 348 Pipe** ppWritePipe) 349 { 350 bool result = false; 351 int sock = -1; 352 int cc; 353 354 assert(ppReadPipe != NULL); 355 assert(ppWritePipe != NULL); 356 357 delete[] mFileName; 358 mFileName = makeFilename(name); 359 360 struct sockaddr_un addr; 361 362 sock = ::socket(AF_UNIX, SOCK_STREAM, 0); 363 if (sock < 0) { 364 LOG(LOG_ERROR, "lbicomm", 365 "UNIX domain socket create failed (errno=%d)\n", errno); 366 goto bail; 367 } 368 369 /* connect to socket; fails if file doesn't exist */ 370 strcpy(addr.sun_path, mFileName); // max 108 bytes 371 addr.sun_family = AF_UNIX; 372 cc = ::connect(sock, (struct sockaddr*) &addr, SUN_LEN(&addr)); 373 if (cc < 0) { 374 // ENOENT means socket file doesn't exist 375 // ECONNREFUSED means socket exists but nobody is listening 376 LOG(LOG_ERROR, "lbicomm", 377 "AF_UNIX connect failed for '%s': %s\n", mFileName,strerror(errno)); 378 goto bail; 379 } 380 381 /* 382 * Create the two halves. We dup() the sock so that closing one side 383 * does not hose the other. 384 */ 385 *ppReadPipe = new Pipe(); 386 (*ppReadPipe)->createReader(sock); 387 *ppWritePipe = new Pipe(); 388 (*ppWritePipe)->createWriter(dup(sock)); 389 390 assert(mHandle == kInvalidHandle); 391 sock = -1; 392 mIsListener = false; 393 394 result = true; 395 396 bail: 397 if (sock >= 0) 398 close(sock); 399 return result; 400 } 401 402 /* 403 * Listen for a new connection. 404 */ 405 bool LocalBiChannel::listen(Pipe** ppReadPipe, Pipe** ppWritePipe) 406 { 407 bool result = false; 408 struct sockaddr_un from; 409 socklen_t fromlen; 410 int sock, lsock; 411 int cc; 412 413 assert(mHandle != kInvalidHandle); 414 lsock = (int) mHandle; 415 416 LOG(LOG_DEBUG, "lbicomm", "AF_UNIX listening\n"); 417 cc = ::listen(lsock, 5); 418 if (cc < 0) { 419 LOG(LOG_ERROR, "lbicomm", "AF_UNIX listen failed (errno=%d)\n", errno); 420 goto bail; 421 } 422 423 fromlen = sizeof(from); // not SUN_LEN() 424 sock = ::accept(lsock, (struct sockaddr*) &from, &fromlen); 425 if (sock < 0) { 426 LOG(LOG_WARN, "lbicomm", "AF_UNIX accept failed (errno=%d)\n", errno); 427 goto bail; 428 } 429 430 /* 431 * Create the two halves. We dup() the sock so that closing one side 432 * does not hose the other. 433 */ 434 *ppReadPipe = new Pipe(); 435 (*ppReadPipe)->createReader(sock); 436 *ppWritePipe = new Pipe(); 437 (*ppWritePipe)->createWriter(dup(sock)); 438 result = true; 439 440 bail: 441 return result; 442 } 443 444 #endif 445