aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp
blob: 7b2f67d7d8d1c697290593b46f7d7be486536bc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "UnixStream.h"

#include "emugl/common/sockets.h"

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/un.h>
#include <sys/stat.h>

/* Not all systems define PATH_MAX, those who don't generally don't
 * have a limit on the maximum path size, so use a value that is
 * large enough for our very limited needs.
 */
#ifndef PATH_MAX
#define PATH_MAX   128
#endif

UnixStream::UnixStream(size_t bufSize) :
    SocketStream(bufSize)
{
}

UnixStream::UnixStream(int sock, size_t bufSize) :
    SocketStream(sock, bufSize)
{
}

/* Initialize a sockaddr_un with the appropriate values corresponding
 * to a given 'virtual port'. Returns 0 on success, -1 on error.
 */
static int
make_unix_path(char *path, size_t  pathlen, int port_number)
{
    char  tmp[PATH_MAX];  // temp directory
    int   ret = 0;

    // First, create user-specific temp directory if needed
    const char* user = getenv("USER");
    if (user != NULL) {
        struct stat  st;
        snprintf(tmp, sizeof(tmp), "/tmp/android-%s", user);
        do {
            ret = ::lstat(tmp, &st);
        } while (ret < 0 && errno == EINTR);

        if (ret < 0 && errno == ENOENT) {
            do {
                ret = ::mkdir(tmp, 0766);
            } while (ret < 0 && errno == EINTR);
            if (ret < 0) {
                ERR("Could not create temp directory: %s", tmp);
                user = NULL;  // will fall-back to /tmp
            }
        }
        else if (ret < 0) {
            user = NULL;  // will fallback to /tmp
        }
    }

    if (user == NULL) {  // fallback to /tmp in case of error
        snprintf(tmp, sizeof(tmp), "/tmp");
    }

    // Now, initialize it properly
    snprintf(path, pathlen, "%s/qemu-gles-%d", tmp, port_number);
    return 0;
}


int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN])
{
    if (make_unix_path(addrstr, MAX_ADDRSTR_LEN, getpid()) < 0) {
        return -1;
    }

    m_sock = emugl::socketLocalServer(addrstr, SOCK_STREAM);
    if (!valid()) return int(ERR_INVALID_SOCKET);

    return 0;
}

SocketStream * UnixStream::accept()
{
    int clientSock = -1;

    while (true) {
        struct sockaddr_un addr;
        socklen_t len = sizeof(addr);
        clientSock = ::accept(m_sock, (sockaddr *)&addr, &len);

        if (clientSock < 0 && errno == EINTR) {
            continue;
        }
        break;
    }

    UnixStream *clientStream = NULL;

    if (clientSock >= 0) {
        clientStream =  new UnixStream(clientSock, m_bufsize);
    }
    return clientStream;
}

int UnixStream::connect(const char* addr)
{
    m_sock = emugl::socketLocalClient(addr, SOCK_STREAM);
    if (!valid()) return -1;

    return 0;
}