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