SocketClient.cpp revision 8702bb17f40022e970e8acd40b348d074e39afc7
1fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <alloca.h>
2fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <errno.h>
330abb7234de2a9caa1add4b00a189436f0b24560Kenny Root#include <sys/socket.h>
4fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <sys/types.h>
5fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <pthread.h>
6d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat#include <string.h>
7fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
8fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#define LOG_TAG "SocketClient"
9fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <cutils/log.h>
10fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
11fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <sysutils/SocketClient.h>
12fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
138702bb17f40022e970e8acd40b348d074e39afc7Robert GreenwaltSocketClient::SocketClient(int socket, bool owned) {
148702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    init(socket, owned, false);
158702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt}
168702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt
178702bb17f40022e970e8acd40b348d074e39afc7Robert GreenwaltSocketClient::SocketClient(int socket, bool owned, bool useCmdNum) {
188702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    init(socket, owned, useCmdNum);
198702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt}
208702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt
218702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwaltvoid SocketClient::init(int socket, bool owned, bool useCmdNum) {
228702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mSocket = socket;
238702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mSocketOwned = owned;
248702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mUseCmdNum = useCmdNum;
25fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_init(&mWriteMutex, NULL);
26648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick    pthread_mutex_init(&mRefCountMutex, NULL);
278702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mPid = -1;
288702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mUid = -1;
298702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mGid = -1;
308702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mRefCount = 1;
318702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mCmdNum = 0;
3230abb7234de2a9caa1add4b00a189436f0b24560Kenny Root
3330abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    struct ucred creds;
3430abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    socklen_t szCreds = sizeof(creds);
3530abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    memset(&creds, 0, szCreds);
3630abb7234de2a9caa1add4b00a189436f0b24560Kenny Root
3730abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
3830abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    if (err == 0) {
3930abb7234de2a9caa1add4b00a189436f0b24560Kenny Root        mPid = creds.pid;
4030abb7234de2a9caa1add4b00a189436f0b24560Kenny Root        mUid = creds.uid;
4130abb7234de2a9caa1add4b00a189436f0b24560Kenny Root        mGid = creds.gid;
4230abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    }
43fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
44fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
454520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu WangSocketClient::~SocketClient()
464520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang{
474520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang    if (mSocketOwned) {
484520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang        close(mSocket);
494520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang    }
504520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang}
514520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang
52db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(int code, const char *msg, bool addErrno) {
538702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    return sendMsg(code, msg, addErrno, mUseCmdNum);
548702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt}
558702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt
568702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwaltint SocketClient::sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum) {
57d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat    char *buf;
588702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    int ret = 0;
5903f0d27f6c49530a91402ed42f8ca4b2fda04b9fSan Mehat
60d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat    if (addErrno) {
618702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        if (useCmdNum) {
628702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            ret = asprintf(&buf, "%d %d %s (%s)", code, getCmdNum(), msg, strerror(errno));
638702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        } else {
648702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            ret = asprintf(&buf, "%d %s (%s)", code, msg, strerror(errno));
658702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        }
66d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat    } else {
678702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        if (useCmdNum) {
688702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            ret = asprintf(&buf, "%d %d %s", code, getCmdNum(), msg);
698702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        } else {
708702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            ret = asprintf(&buf, "%d %s", code, msg);
718702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        }
72d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat    }
73af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner    /* Send the zero-terminated message */
748702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    if (ret != -1) {
758702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        ret = sendMsg(buf);
768702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        free(buf);
778702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    }
788702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    return ret;
79d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat}
80d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat
81db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(const char *msg) {
82fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    if (mSocket < 0) {
83fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        errno = EHOSTUNREACH;
84fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
85fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    }
86fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
87c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat    // Send the message including null character
888c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick    if (sendData(msg, strlen(msg) + 1) != 0) {
898c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick        SLOGW("Unable to send msg '%s'", msg);
908c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick        return -1;
918c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick    }
928c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick    return 0;
938c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick}
948c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick
958c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrickint SocketClient::sendData(const void* data, int len) {
96d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat    int rc = 0;
978c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick    const char *p = (const char*) data;
988c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick    int brtw = len;
99d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat
10016ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick    if (len == 0) {
10116ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick        return 0;
10216ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick    }
10316ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick
104fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_lock(&mWriteMutex);
1058c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick    while (brtw > 0) {
106af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        rc = write(mSocket, p, brtw);
107af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        if (rc > 0) {
108af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner            p += rc;
109af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner            brtw -= rc;
110af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner            continue;
111af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        }
112af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner
113af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        if (rc < 0 && errno == EINTR)
114af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner            continue;
115af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner
116af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        pthread_mutex_unlock(&mWriteMutex);
117af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        if (rc == 0) {
1187e8529a8b528fd30586aa037f15a31b29582c537San Mehat            SLOGW("0 length write :(");
119d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat            errno = EIO;
120af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        } else {
121af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner            SLOGW("write error (%s)", strerror(errno));
122d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat        }
123af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        return -1;
124fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    }
125fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_unlock(&mWriteMutex);
126fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    return 0;
127fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
128648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick
129648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrickvoid SocketClient::incRef() {
1304be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    pthread_mutex_lock(&mRefCountMutex);
1314be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    mRefCount++;
1324be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    pthread_mutex_unlock(&mRefCountMutex);
133648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick}
134648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick
1354be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrickbool SocketClient::decRef() {
1364be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    bool deleteSelf = false;
1374be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    pthread_mutex_lock(&mRefCountMutex);
1384be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    mRefCount--;
1394be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    if (mRefCount == 0) {
1404be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick        deleteSelf = true;
1414be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    } else if (mRefCount < 0) {
1424be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick        SLOGE("SocketClient refcount went negative!");
1434be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    }
1444be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    pthread_mutex_unlock(&mRefCountMutex);
1454be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    if (deleteSelf) {
1464be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick        delete this;
1474be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    }
1484be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    return deleteSelf;
149648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick}
150