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 #include "UnixStream.h" 17 #include <cutils/sockets.h> 18 #include <errno.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <string.h> 23 24 #include <netinet/in.h> 25 #include <netinet/tcp.h> 26 #include <sys/un.h> 27 #include <sys/stat.h> 28 29 /* Not all systems define PATH_MAX, those who don't generally don't 30 * have a limit on the maximum path size, so use a value that is 31 * large enough for our very limited needs. 32 */ 33 #ifndef PATH_MAX 34 #define PATH_MAX 128 35 #endif 36 37 UnixStream::UnixStream(size_t bufSize) : 38 SocketStream(bufSize) 39 { 40 } 41 42 UnixStream::UnixStream(int sock, size_t bufSize) : 43 SocketStream(sock, bufSize) 44 { 45 } 46 47 /* Initialize a sockaddr_un with the appropriate values corresponding 48 * to a given 'virtual port'. Returns 0 on success, -1 on error. 49 */ 50 static int 51 make_unix_path(char *path, size_t pathlen, int port_number) 52 { 53 char tmp[PATH_MAX]; // temp directory 54 int ret = 0; 55 56 // First, create user-specific temp directory if needed 57 const char* user = getenv("USER"); 58 if (user != NULL) { 59 struct stat st; 60 snprintf(tmp, sizeof(tmp), "/tmp/android-%s", user); 61 do { 62 ret = ::lstat(tmp, &st); 63 } while (ret < 0 && errno == EINTR); 64 65 if (ret < 0 && errno == ENOENT) { 66 do { 67 ret = ::mkdir(tmp, 0766); 68 } while (ret < 0 && errno == EINTR); 69 if (ret < 0) { 70 ERR("Could not create temp directory: %s", tmp); 71 user = NULL; // will fall-back to /tmp 72 } 73 } 74 else if (ret < 0) { 75 user = NULL; // will fallback to /tmp 76 } 77 } 78 79 if (user == NULL) { // fallback to /tmp in case of error 80 snprintf(tmp, sizeof(tmp), "/tmp"); 81 } 82 83 // Now, initialize it properly 84 snprintf(path, pathlen, "%s/qemu-gles-%d", tmp, port_number); 85 return 0; 86 } 87 88 89 int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN]) 90 { 91 if (make_unix_path(addrstr, MAX_ADDRSTR_LEN, getpid()) < 0) { 92 return -1; 93 } 94 95 m_sock = socket_local_server(addrstr, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); 96 if (!valid()) return int(ERR_INVALID_SOCKET); 97 98 return 0; 99 } 100 101 SocketStream * UnixStream::accept() 102 { 103 int clientSock = -1; 104 105 while (true) { 106 struct sockaddr_un addr; 107 socklen_t len = sizeof(addr); 108 clientSock = ::accept(m_sock, (sockaddr *)&addr, &len); 109 110 if (clientSock < 0 && errno == EINTR) { 111 continue; 112 } 113 break; 114 } 115 116 UnixStream *clientStream = NULL; 117 118 if (clientSock >= 0) { 119 clientStream = new UnixStream(clientSock, m_bufsize); 120 } 121 return clientStream; 122 } 123 124 int UnixStream::connect(const char* addr) 125 { 126 m_sock = socket_local_client(addr, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); 127 if (!valid()) return -1; 128 129 return 0; 130 } 131