SocketClient.cpp revision 648ebad883e7825353c841950dd7d78664c238e6
1#include <alloca.h>
2#include <errno.h>
3#include <sys/socket.h>
4#include <sys/types.h>
5#include <pthread.h>
6#include <string.h>
7
8#define LOG_TAG "SocketClient"
9#include <cutils/log.h>
10
11#include <sysutils/SocketClient.h>
12
13SocketClient::SocketClient(int socket)
14        : mSocket(socket)
15        , mPid(-1)
16        , mUid(-1)
17        , mGid(-1)
18        , mRefCount(1)
19{
20    pthread_mutex_init(&mWriteMutex, NULL);
21    pthread_mutex_init(&mRefCountMutex, NULL);
22
23    struct ucred creds;
24    socklen_t szCreds = sizeof(creds);
25    memset(&creds, 0, szCreds);
26
27    int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
28    if (err == 0) {
29        mPid = creds.pid;
30        mUid = creds.uid;
31        mGid = creds.gid;
32    }
33}
34
35int SocketClient::sendMsg(int code, const char *msg, bool addErrno) {
36    char *buf;
37    const char* arg;
38    const char* fmt;
39    char tmp[1];
40    int  len;
41
42    if (addErrno) {
43        fmt = "%.3d %s (%s)";
44        arg = strerror(errno);
45    } else {
46        fmt = "%.3d %s";
47        arg = NULL;
48    }
49    /* Measure length of required buffer */
50    len = snprintf(tmp, sizeof tmp, fmt, code, msg, arg);
51    /* Allocate in the stack, then write to it */
52    buf = (char*)alloca(len+1);
53    snprintf(buf, len+1, fmt, code, msg, arg);
54    /* Send the zero-terminated message */
55    return sendMsg(buf);
56}
57
58int SocketClient::sendMsg(const char *msg) {
59    if (mSocket < 0) {
60        errno = EHOSTUNREACH;
61        return -1;
62    }
63
64    // Send the message including null character
65    if (sendData(msg, strlen(msg) + 1) != 0) {
66        SLOGW("Unable to send msg '%s'", msg);
67        return -1;
68    }
69    return 0;
70}
71
72int SocketClient::sendData(const void* data, int len) {
73    int rc = 0;
74    const char *p = (const char*) data;
75    int brtw = len;
76
77    if (len == 0) {
78        return 0;
79    }
80
81    pthread_mutex_lock(&mWriteMutex);
82    while (brtw > 0) {
83        rc = write(mSocket, p, brtw);
84        if (rc > 0) {
85            p += rc;
86            brtw -= rc;
87            continue;
88        }
89
90        if (rc < 0 && errno == EINTR)
91            continue;
92
93        pthread_mutex_unlock(&mWriteMutex);
94        if (rc == 0) {
95            SLOGW("0 length write :(");
96            errno = EIO;
97        } else {
98            SLOGW("write error (%s)", strerror(errno));
99        }
100        return -1;
101    }
102    pthread_mutex_unlock(&mWriteMutex);
103    return 0;
104}
105
106void SocketClient::incRef() {
107  pthread_mutex_lock(&mRefCountMutex);
108  mRefCount++;
109  pthread_mutex_unlock(&mRefCountMutex);
110}
111
112void SocketClient::decRef() {
113  bool deleteSelf = false;
114  pthread_mutex_lock(&mRefCountMutex);
115  mRefCount--;
116  if (mRefCount == 0) {
117      deleteSelf = true;
118  }
119  pthread_mutex_unlock(&mRefCountMutex);
120  if (deleteSelf) {
121      delete this;
122  }
123}
124