SocketClient.cpp revision 8702bb17f40022e970e8acd40b348d074e39afc7
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, bool owned) {
14    init(socket, owned, false);
15}
16
17SocketClient::SocketClient(int socket, bool owned, bool useCmdNum) {
18    init(socket, owned, useCmdNum);
19}
20
21void SocketClient::init(int socket, bool owned, bool useCmdNum) {
22    mSocket = socket;
23    mSocketOwned = owned;
24    mUseCmdNum = useCmdNum;
25    pthread_mutex_init(&mWriteMutex, NULL);
26    pthread_mutex_init(&mRefCountMutex, NULL);
27    mPid = -1;
28    mUid = -1;
29    mGid = -1;
30    mRefCount = 1;
31    mCmdNum = 0;
32
33    struct ucred creds;
34    socklen_t szCreds = sizeof(creds);
35    memset(&creds, 0, szCreds);
36
37    int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
38    if (err == 0) {
39        mPid = creds.pid;
40        mUid = creds.uid;
41        mGid = creds.gid;
42    }
43}
44
45SocketClient::~SocketClient()
46{
47    if (mSocketOwned) {
48        close(mSocket);
49    }
50}
51
52int SocketClient::sendMsg(int code, const char *msg, bool addErrno) {
53    return sendMsg(code, msg, addErrno, mUseCmdNum);
54}
55
56int SocketClient::sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum) {
57    char *buf;
58    int ret = 0;
59
60    if (addErrno) {
61        if (useCmdNum) {
62            ret = asprintf(&buf, "%d %d %s (%s)", code, getCmdNum(), msg, strerror(errno));
63        } else {
64            ret = asprintf(&buf, "%d %s (%s)", code, msg, strerror(errno));
65        }
66    } else {
67        if (useCmdNum) {
68            ret = asprintf(&buf, "%d %d %s", code, getCmdNum(), msg);
69        } else {
70            ret = asprintf(&buf, "%d %s", code, msg);
71        }
72    }
73    /* Send the zero-terminated message */
74    if (ret != -1) {
75        ret = sendMsg(buf);
76        free(buf);
77    }
78    return ret;
79}
80
81int SocketClient::sendMsg(const char *msg) {
82    if (mSocket < 0) {
83        errno = EHOSTUNREACH;
84        return -1;
85    }
86
87    // Send the message including null character
88    if (sendData(msg, strlen(msg) + 1) != 0) {
89        SLOGW("Unable to send msg '%s'", msg);
90        return -1;
91    }
92    return 0;
93}
94
95int SocketClient::sendData(const void* data, int len) {
96    int rc = 0;
97    const char *p = (const char*) data;
98    int brtw = len;
99
100    if (len == 0) {
101        return 0;
102    }
103
104    pthread_mutex_lock(&mWriteMutex);
105    while (brtw > 0) {
106        rc = write(mSocket, p, brtw);
107        if (rc > 0) {
108            p += rc;
109            brtw -= rc;
110            continue;
111        }
112
113        if (rc < 0 && errno == EINTR)
114            continue;
115
116        pthread_mutex_unlock(&mWriteMutex);
117        if (rc == 0) {
118            SLOGW("0 length write :(");
119            errno = EIO;
120        } else {
121            SLOGW("write error (%s)", strerror(errno));
122        }
123        return -1;
124    }
125    pthread_mutex_unlock(&mWriteMutex);
126    return 0;
127}
128
129void SocketClient::incRef() {
130    pthread_mutex_lock(&mRefCountMutex);
131    mRefCount++;
132    pthread_mutex_unlock(&mRefCountMutex);
133}
134
135bool SocketClient::decRef() {
136    bool deleteSelf = false;
137    pthread_mutex_lock(&mRefCountMutex);
138    mRefCount--;
139    if (mRefCount == 0) {
140        deleteSelf = true;
141    } else if (mRefCount < 0) {
142        SLOGE("SocketClient refcount went negative!");
143    }
144    pthread_mutex_unlock(&mRefCountMutex);
145    if (deleteSelf) {
146        delete this;
147    }
148    return deleteSelf;
149}
150