10469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy/*
20469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * Copyright 2011, The Android Open Source Project
30469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
40469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * Licensed under the Apache License, Version 2.0 (the "License");
50469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * you may not use this file except in compliance with the License.
60469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * You may obtain a copy of the License at
70469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
80469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *     http://www.apache.org/licenses/LICENSE-2.0
90469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * Unless required by applicable law or agreed to in writing, software
110469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * distributed under the License is distributed on an "AS IS" BASIS,
120469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * See the License for the specific language governing permissions and
140469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * limitations under the License.
150469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy */
160469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
172fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy#include <errno.h>
180469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include <stdlib.h>
190469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include <unistd.h>
200469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
210832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy#include <unistd.h>
220469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include <sys/socket.h>
230832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy#include <sys/un.h>
240469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include <netinet/in.h>
250469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
260469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include <cutils/log.h>
278e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy#include <private/android_filesystem_config.h>
280469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
290469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "gltrace_transport.h"
300469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
310469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamynamespace android {
320469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamynamespace gltrace {
330469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
340832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamyint acceptClientConnection(char *sockname) {
350832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    int serverSocket = socket(AF_LOCAL, SOCK_STREAM, 0);
3693a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (serverSocket < 0) {
37e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block        ALOGE("Error (%d) while creating socket. Check if app has network permissions.",
3893a826f78f6313db791e6fc880439189897651b3Siva Velusamy                                                                            serverSocket);
3993a826f78f6313db791e6fc880439189897651b3Siva Velusamy        return -1;
400469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    }
410469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
420832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    struct sockaddr_un server, client;
430469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
440832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    memset(&server, 0, sizeof server);
450832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    server.sun_family = AF_UNIX;
460832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    // the first byte of sun_path should be '\0' for abstract namespace
470832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    strcpy(server.sun_path + 1, sockname);
480469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
490832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    // note that sockaddr_len should be set to the exact size of the buffer that is used.
500832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    socklen_t sockaddr_len = sizeof(server.sun_family) + strlen(sockname) + 1;
510832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    if (bind(serverSocket, (struct sockaddr *) &server, sockaddr_len) < 0) {
5293a826f78f6313db791e6fc880439189897651b3Siva Velusamy        close(serverSocket);
53e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block        ALOGE("Failed to bind the server socket");
5493a826f78f6313db791e6fc880439189897651b3Siva Velusamy        return -1;
550469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    }
560469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
5793a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (listen(serverSocket, 1) < 0) {
5893a826f78f6313db791e6fc880439189897651b3Siva Velusamy        close(serverSocket);
59e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block        ALOGE("Failed to listen on server socket");
6093a826f78f6313db791e6fc880439189897651b3Siva Velusamy        return -1;
610469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    }
620469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
630832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    ALOGD("gltrace::waitForClientConnection: server listening @ path %s", sockname);
640469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
6593a826f78f6313db791e6fc880439189897651b3Siva Velusamy    int clientSocket = accept(serverSocket, (struct sockaddr *)&client, &sockaddr_len);
6693a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (clientSocket < 0) {
6793a826f78f6313db791e6fc880439189897651b3Siva Velusamy        close(serverSocket);
68e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block        ALOGE("Failed to accept client connection");
6993a826f78f6313db791e6fc880439189897651b3Siva Velusamy        return -1;
700469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    }
710469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
728e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy    struct ucred cr;
738e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy    socklen_t cr_len = sizeof(cr);
748e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy    if (getsockopt(clientSocket, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0) {
758e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy        ALOGE("Error obtaining credentials of peer");
768e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy        return -1;
778e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy    }
788e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy
79c7d767ad57a25eeefbbfe2610396d800f04178edSiva Velusamy    // Only accept connects from the shell (adb forward comes to us as shell user),
80c7d767ad57a25eeefbbfe2610396d800f04178edSiva Velusamy    // or the root user.
81c7d767ad57a25eeefbbfe2610396d800f04178edSiva Velusamy    if (cr.uid != AID_SHELL && cr.uid != AID_ROOT) {
828e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy        ALOGE("Unknown peer type (%d), expected shell to be the peer", cr.uid);
838e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy        return -1;
848e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy    }
858e2f3858d5a06dae5a543d9428278f59120f7f8cSiva Velusamy
860832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    ALOGD("gltrace::waitForClientConnection: client connected.");
8793a826f78f6313db791e6fc880439189897651b3Siva Velusamy
8893a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // do not accept any more incoming connections
8993a826f78f6313db791e6fc880439189897651b3Siva Velusamy    close(serverSocket);
9093a826f78f6313db791e6fc880439189897651b3Siva Velusamy
9193a826f78f6313db791e6fc880439189897651b3Siva Velusamy    return clientSocket;
9293a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
9393a826f78f6313db791e6fc880439189897651b3Siva Velusamy
9493a826f78f6313db791e6fc880439189897651b3Siva VelusamyTCPStream::TCPStream(int socket) {
9593a826f78f6313db791e6fc880439189897651b3Siva Velusamy    mSocket = socket;
9693a826f78f6313db791e6fc880439189897651b3Siva Velusamy    pthread_mutex_init(&mSocketWriteMutex, NULL);
970469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
980469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
9993a826f78f6313db791e6fc880439189897651b3Siva VelusamyTCPStream::~TCPStream() {
10093a826f78f6313db791e6fc880439189897651b3Siva Velusamy    pthread_mutex_destroy(&mSocketWriteMutex);
10193a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
10293a826f78f6313db791e6fc880439189897651b3Siva Velusamy
10393a826f78f6313db791e6fc880439189897651b3Siva Velusamyvoid TCPStream::closeStream() {
10493a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (mSocket > 0) {
10593a826f78f6313db791e6fc880439189897651b3Siva Velusamy        close(mSocket);
10693a826f78f6313db791e6fc880439189897651b3Siva Velusamy        mSocket = 0;
1070469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    }
1080469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
1090469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
11093a826f78f6313db791e6fc880439189897651b3Siva Velusamyint TCPStream::send(void *buf, size_t len) {
11193a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (mSocket <= 0) {
11293a826f78f6313db791e6fc880439189897651b3Siva Velusamy        return -1;
1130469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    }
1140469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
11593a826f78f6313db791e6fc880439189897651b3Siva Velusamy    pthread_mutex_lock(&mSocketWriteMutex);
11693a826f78f6313db791e6fc880439189897651b3Siva Velusamy    int n = write(mSocket, buf, len);
11793a826f78f6313db791e6fc880439189897651b3Siva Velusamy    pthread_mutex_unlock(&mSocketWriteMutex);
11893a826f78f6313db791e6fc880439189897651b3Siva Velusamy
11993a826f78f6313db791e6fc880439189897651b3Siva Velusamy    return n;
12093a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
1210469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
12293a826f78f6313db791e6fc880439189897651b3Siva Velusamyint TCPStream::receive(void *data, size_t len) {
12393a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (mSocket <= 0) {
12493a826f78f6313db791e6fc880439189897651b3Siva Velusamy        return -1;
1250469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    }
1260469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1272fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    size_t totalRead = 0;
1282fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    while (totalRead < len) {
1292fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        int n = read(mSocket, (uint8_t*)data + totalRead, len - totalRead);
1302fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        if (n < 0) {
1312fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            ALOGE("Error receiving data from stream: %d", errno);
1322fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            return -1;
1332fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        }
1342fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
1352fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        totalRead += n;
1362fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    }
1372fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
1382fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    return 0;
13993a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
14093a826f78f6313db791e6fc880439189897651b3Siva Velusamy
14193a826f78f6313db791e6fc880439189897651b3Siva VelusamyBufferedOutputStream::BufferedOutputStream(TCPStream *stream, size_t bufferSize) {
14293a826f78f6313db791e6fc880439189897651b3Siva Velusamy    mStream = stream;
14393a826f78f6313db791e6fc880439189897651b3Siva Velusamy
14493a826f78f6313db791e6fc880439189897651b3Siva Velusamy    mBufferSize = bufferSize;
14593a826f78f6313db791e6fc880439189897651b3Siva Velusamy    mStringBuffer = "";
14693a826f78f6313db791e6fc880439189897651b3Siva Velusamy    mStringBuffer.reserve(bufferSize);
14793a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
14893a826f78f6313db791e6fc880439189897651b3Siva Velusamy
14993a826f78f6313db791e6fc880439189897651b3Siva Velusamyint BufferedOutputStream::flush() {
15093a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (mStringBuffer.size() == 0) {
15193a826f78f6313db791e6fc880439189897651b3Siva Velusamy        return 0;
15293a826f78f6313db791e6fc880439189897651b3Siva Velusamy    }
15393a826f78f6313db791e6fc880439189897651b3Siva Velusamy
15493a826f78f6313db791e6fc880439189897651b3Siva Velusamy    int n = mStream->send((void *)mStringBuffer.data(), mStringBuffer.size());
15593a826f78f6313db791e6fc880439189897651b3Siva Velusamy    mStringBuffer.clear();
15693a826f78f6313db791e6fc880439189897651b3Siva Velusamy    return n;
15793a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
15893a826f78f6313db791e6fc880439189897651b3Siva Velusamy
15993a826f78f6313db791e6fc880439189897651b3Siva Velusamyvoid BufferedOutputStream::enqueueMessage(GLMessage *msg) {
16093a826f78f6313db791e6fc880439189897651b3Siva Velusamy    const uint32_t len = msg->ByteSize();
16193a826f78f6313db791e6fc880439189897651b3Siva Velusamy
16293a826f78f6313db791e6fc880439189897651b3Siva Velusamy    mStringBuffer.append((const char *)&len, sizeof(len));    // append header
16393a826f78f6313db791e6fc880439189897651b3Siva Velusamy    msg->AppendToString(&mStringBuffer);                      // append message
16493a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
16593a826f78f6313db791e6fc880439189897651b3Siva Velusamy
16693a826f78f6313db791e6fc880439189897651b3Siva Velusamyint BufferedOutputStream::send(GLMessage *msg) {
16793a826f78f6313db791e6fc880439189897651b3Siva Velusamy    enqueueMessage(msg);
16893a826f78f6313db791e6fc880439189897651b3Siva Velusamy
16993a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (mStringBuffer.size() > mBufferSize) {
17093a826f78f6313db791e6fc880439189897651b3Siva Velusamy        return flush();
1710469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    }
17293a826f78f6313db791e6fc880439189897651b3Siva Velusamy
17393a826f78f6313db791e6fc880439189897651b3Siva Velusamy    return 0;
1740469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
1750469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1760469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy};  // namespace gltrace
1770469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy};  // namespace android
178