gltrace_transport.cpp revision 8e2f3858d5a06dae5a543d9428278f59120f7f8c
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 if (cr.uid != AID_SHELL) { 80 ALOGE("Unknown peer type (%d), expected shell to be the peer", cr.uid); 81 return -1; 82 } 83 84 ALOGD("gltrace::waitForClientConnection: client connected."); 85 86 // do not accept any more incoming connections 87 close(serverSocket); 88 89 return clientSocket; 90} 91 92TCPStream::TCPStream(int socket) { 93 mSocket = socket; 94 pthread_mutex_init(&mSocketWriteMutex, NULL); 95} 96 97TCPStream::~TCPStream() { 98 pthread_mutex_destroy(&mSocketWriteMutex); 99} 100 101void TCPStream::closeStream() { 102 if (mSocket > 0) { 103 close(mSocket); 104 mSocket = 0; 105 } 106} 107 108int TCPStream::send(void *buf, size_t len) { 109 if (mSocket <= 0) { 110 return -1; 111 } 112 113 pthread_mutex_lock(&mSocketWriteMutex); 114 int n = write(mSocket, buf, len); 115 pthread_mutex_unlock(&mSocketWriteMutex); 116 117 return n; 118} 119 120int TCPStream::receive(void *data, size_t len) { 121 if (mSocket <= 0) { 122 return -1; 123 } 124 125 return read(mSocket, data, len); 126} 127 128BufferedOutputStream::BufferedOutputStream(TCPStream *stream, size_t bufferSize) { 129 mStream = stream; 130 131 mBufferSize = bufferSize; 132 mStringBuffer = ""; 133 mStringBuffer.reserve(bufferSize); 134} 135 136int BufferedOutputStream::flush() { 137 if (mStringBuffer.size() == 0) { 138 return 0; 139 } 140 141 int n = mStream->send((void *)mStringBuffer.data(), mStringBuffer.size()); 142 mStringBuffer.clear(); 143 return n; 144} 145 146void BufferedOutputStream::enqueueMessage(GLMessage *msg) { 147 const uint32_t len = msg->ByteSize(); 148 149 mStringBuffer.append((const char *)&len, sizeof(len)); // append header 150 msg->AppendToString(&mStringBuffer); // append message 151} 152 153int BufferedOutputStream::send(GLMessage *msg) { 154 enqueueMessage(msg); 155 156 if (mStringBuffer.size() > mBufferSize) { 157 return flush(); 158 } 159 160 return 0; 161} 162 163}; // namespace gltrace 164}; // namespace android 165