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