1 /* 2 * Copyright 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 #include <errno.h> 18 #include <stdlib.h> 19 #include <unistd.h> 20 21 #include <unistd.h> 22 #include <sys/socket.h> 23 #include <sys/un.h> 24 #include <netinet/in.h> 25 26 #include <cutils/log.h> 27 #include <private/android_filesystem_config.h> 28 29 #include "gltrace_transport.h" 30 31 namespace android { 32 namespace gltrace { 33 34 int acceptClientConnection(char *sockname) { 35 int serverSocket = socket(AF_LOCAL, SOCK_STREAM, 0); 36 if (serverSocket < 0) { 37 ALOGE("Error (%d) while creating socket. Check if app has network permissions.", 38 serverSocket); 39 return -1; 40 } 41 42 struct sockaddr_un server, client; 43 44 memset(&server, 0, sizeof server); 45 server.sun_family = AF_UNIX; 46 // the first byte of sun_path should be '\0' for abstract namespace 47 strcpy(server.sun_path + 1, sockname); 48 49 // note that sockaddr_len should be set to the exact size of the buffer that is used. 50 socklen_t sockaddr_len = sizeof(server.sun_family) + strlen(sockname) + 1; 51 if (bind(serverSocket, (struct sockaddr *) &server, sockaddr_len) < 0) { 52 close(serverSocket); 53 ALOGE("Failed to bind the server socket"); 54 return -1; 55 } 56 57 if (listen(serverSocket, 1) < 0) { 58 close(serverSocket); 59 ALOGE("Failed to listen on server socket"); 60 return -1; 61 } 62 63 ALOGD("gltrace::waitForClientConnection: server listening @ path %s", sockname); 64 65 int clientSocket = accept(serverSocket, (struct sockaddr *)&client, &sockaddr_len); 66 if (clientSocket < 0) { 67 close(serverSocket); 68 ALOGE("Failed to accept client connection"); 69 return -1; 70 } 71 72 struct ucred cr; 73 socklen_t cr_len = sizeof(cr); 74 if (getsockopt(clientSocket, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0) { 75 ALOGE("Error obtaining credentials of peer"); 76 return -1; 77 } 78 79 // Only accept connects from the shell (adb forward comes to us as shell user), 80 // or the root user. 81 if (cr.uid != AID_SHELL && cr.uid != AID_ROOT) { 82 ALOGE("Unknown peer type (%d), expected shell to be the peer", cr.uid); 83 return -1; 84 } 85 86 ALOGD("gltrace::waitForClientConnection: client connected."); 87 88 // do not accept any more incoming connections 89 close(serverSocket); 90 91 return clientSocket; 92 } 93 94 TCPStream::TCPStream(int socket) { 95 mSocket = socket; 96 pthread_mutex_init(&mSocketWriteMutex, NULL); 97 } 98 99 TCPStream::~TCPStream() { 100 pthread_mutex_destroy(&mSocketWriteMutex); 101 } 102 103 void TCPStream::closeStream() { 104 if (mSocket > 0) { 105 close(mSocket); 106 mSocket = 0; 107 } 108 } 109 110 int TCPStream::send(void *buf, size_t len) { 111 if (mSocket <= 0) { 112 return -1; 113 } 114 115 pthread_mutex_lock(&mSocketWriteMutex); 116 int n = write(mSocket, buf, len); 117 pthread_mutex_unlock(&mSocketWriteMutex); 118 119 return n; 120 } 121 122 int TCPStream::receive(void *data, size_t len) { 123 if (mSocket <= 0) { 124 return -1; 125 } 126 127 size_t totalRead = 0; 128 while (totalRead < len) { 129 int n = read(mSocket, (uint8_t*)data + totalRead, len - totalRead); 130 if (n < 0) { 131 ALOGE("Error receiving data from stream: %d", errno); 132 return -1; 133 } 134 135 totalRead += n; 136 } 137 138 return 0; 139 } 140 141 BufferedOutputStream::BufferedOutputStream(TCPStream *stream, size_t bufferSize) { 142 mStream = stream; 143 144 mBufferSize = bufferSize; 145 mStringBuffer = ""; 146 mStringBuffer.reserve(bufferSize); 147 } 148 149 int BufferedOutputStream::flush() { 150 if (mStringBuffer.size() == 0) { 151 return 0; 152 } 153 154 int n = mStream->send((void *)mStringBuffer.data(), mStringBuffer.size()); 155 mStringBuffer.clear(); 156 return n; 157 } 158 159 void BufferedOutputStream::enqueueMessage(GLMessage *msg) { 160 const uint32_t len = msg->ByteSize(); 161 162 mStringBuffer.append((const char *)&len, sizeof(len)); // append header 163 msg->AppendToString(&mStringBuffer); // append message 164 } 165 166 int BufferedOutputStream::send(GLMessage *msg) { 167 enqueueMessage(msg); 168 169 if (mStringBuffer.size() > mBufferSize) { 170 return flush(); 171 } 172 173 return 0; 174 } 175 176 }; // namespace gltrace 177 }; // namespace android 178