1fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <alloca.h>
2fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <errno.h>
3a744b05984a963966cec08758ffe582d241be9d7Elliott Hughes#include <malloc.h>
4fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <pthread.h>
54389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn#include <signal.h>
6d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat#include <string.h>
77bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun#include <arpa/inet.h>
84389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn#include <sys/socket.h>
94389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn#include <sys/types.h>
10fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
11fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#define LOG_TAG "SocketClient"
12fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <cutils/log.h>
13fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
14fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <sysutils/SocketClient.h>
15fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
168702bb17f40022e970e8acd40b348d074e39afc7Robert GreenwaltSocketClient::SocketClient(int socket, bool owned) {
178702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    init(socket, owned, false);
188702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt}
198702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt
208702bb17f40022e970e8acd40b348d074e39afc7Robert GreenwaltSocketClient::SocketClient(int socket, bool owned, bool useCmdNum) {
218702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    init(socket, owned, useCmdNum);
228702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt}
238702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt
248702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwaltvoid SocketClient::init(int socket, bool owned, bool useCmdNum) {
258702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mSocket = socket;
268702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mSocketOwned = owned;
278702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mUseCmdNum = useCmdNum;
28fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_init(&mWriteMutex, NULL);
29648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick    pthread_mutex_init(&mRefCountMutex, NULL);
308702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mPid = -1;
318702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mUid = -1;
328702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mGid = -1;
338702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mRefCount = 1;
348702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mCmdNum = 0;
3530abb7234de2a9caa1add4b00a189436f0b24560Kenny Root
3630abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    struct ucred creds;
3730abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    socklen_t szCreds = sizeof(creds);
3830abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    memset(&creds, 0, szCreds);
3930abb7234de2a9caa1add4b00a189436f0b24560Kenny Root
4030abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
4130abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    if (err == 0) {
4230abb7234de2a9caa1add4b00a189436f0b24560Kenny Root        mPid = creds.pid;
4330abb7234de2a9caa1add4b00a189436f0b24560Kenny Root        mUid = creds.uid;
4430abb7234de2a9caa1add4b00a189436f0b24560Kenny Root        mGid = creds.gid;
4530abb7234de2a9caa1add4b00a189436f0b24560Kenny Root    }
46fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
47fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
484389588e8ded66148d9e616aa20307cf25144460Mark SalyzynSocketClient::~SocketClient() {
494520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang    if (mSocketOwned) {
504520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang        close(mSocket);
514520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang    }
524520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang}
534520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang
54db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(int code, const char *msg, bool addErrno) {
558702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    return sendMsg(code, msg, addErrno, mUseCmdNum);
568702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt}
578702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt
588702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwaltint SocketClient::sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum) {
59d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat    char *buf;
608702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    int ret = 0;
6103f0d27f6c49530a91402ed42f8ca4b2fda04b9fSan Mehat
62d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat    if (addErrno) {
638702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        if (useCmdNum) {
648702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            ret = asprintf(&buf, "%d %d %s (%s)", code, getCmdNum(), msg, strerror(errno));
658702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        } else {
668702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            ret = asprintf(&buf, "%d %s (%s)", code, msg, strerror(errno));
678702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        }
68d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat    } else {
698702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        if (useCmdNum) {
708702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            ret = asprintf(&buf, "%d %d %s", code, getCmdNum(), msg);
718702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        } else {
728702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            ret = asprintf(&buf, "%d %s", code, msg);
738702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        }
74d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat    }
7523f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    // Send the zero-terminated message
768702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    if (ret != -1) {
778702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        ret = sendMsg(buf);
788702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        free(buf);
798702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    }
808702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    return ret;
81d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat}
82d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat
8323f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn// send 3-digit code, null, binary-length, binary data
847bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendBinaryMsg(int code, const void *data, int len) {
857bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun
8623f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    // 4 bytes for the code & null + 4 bytes for the len
877599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt    char buf[8];
8823f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    // Write the code
897599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt    snprintf(buf, 4, "%.3d", code);
9023f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    // Write the len
917bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun    uint32_t tmp = htonl(len);
927599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt    memcpy(buf + 4, &tmp, sizeof(uint32_t));
937bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun
9423f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    struct iovec vec[2];
9523f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    vec[0].iov_base = (void *) buf;
9623f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    vec[0].iov_len = sizeof(buf);
9723f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    vec[1].iov_base = (void *) data;
9823f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    vec[1].iov_len = len;
9923f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn
1007bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun    pthread_mutex_lock(&mWriteMutex);
10123f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    int result = sendDataLockedv(vec, (len > 0) ? 2 : 1);
1027bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun    pthread_mutex_unlock(&mWriteMutex);
1037bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun
1047bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun    return result;
1057bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun}
1067bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun
1077bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun// Sends the code (c-string null-terminated).
1087bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendCode(int code) {
1097599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt    char buf[4];
1107599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt    snprintf(buf, sizeof(buf), "%.3d", code);
1117599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt    return sendData(buf, sizeof(buf));
1127bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun}
1137bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun
114594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwaltchar *SocketClient::quoteArg(const char *arg) {
115594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    int len = strlen(arg);
116594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    char *result = (char *)malloc(len * 2 + 3);
117594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    char *current = result;
118594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    const char *end = arg + len;
119544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li    char *oldresult;
120544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li
121544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li    if(result == NULL) {
122544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li        SLOGW("malloc error (%s)", strerror(errno));
123544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li        return NULL;
124544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li    }
125594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt
126594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    *(current++) = '"';
127594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    while (arg < end) {
128594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt        switch (*arg) {
129594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt        case '\\':
130594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt        case '"':
131594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt            *(current++) = '\\'; // fallthrough
132594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt        default:
133594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt            *(current++) = *(arg++);
134594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt        }
135594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    }
136594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    *(current++) = '"';
137594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    *(current++) = '\0';
138544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li    oldresult = result; // save pointer in case realloc fails
139594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt    result = (char *)realloc(result, current-result);
140544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li    return result ? result : oldresult;
141594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt}
142594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt
143594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt
144db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(const char *msg) {
145c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat    // Send the message including null character
1468c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick    if (sendData(msg, strlen(msg) + 1) != 0) {
1478c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick        SLOGW("Unable to send msg '%s'", msg);
1488c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick        return -1;
1498c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick    }
1508c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick    return 0;
1518c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick}
1528c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick
1537bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendData(const void *data, int len) {
15423f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    struct iovec vec[1];
15523f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    vec[0].iov_base = (void *) data;
15623f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    vec[0].iov_len = len;
1577bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun
1587bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun    pthread_mutex_lock(&mWriteMutex);
15923f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    int rc = sendDataLockedv(vec, 1);
1607bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun    pthread_mutex_unlock(&mWriteMutex);
1617bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun
1627bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun    return rc;
1637bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun}
1647bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun
16523f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzynint SocketClient::sendDatav(struct iovec *iov, int iovcnt) {
16623f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    pthread_mutex_lock(&mWriteMutex);
16723f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    int rc = sendDataLockedv(iov, iovcnt);
16823f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    pthread_mutex_unlock(&mWriteMutex);
16923f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn
17023f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    return rc;
17123f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn}
17223f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn
17323f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzynint SocketClient::sendDataLockedv(struct iovec *iov, int iovcnt) {
174d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat
1752e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk    if (mSocket < 0) {
1762e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk        errno = EHOSTUNREACH;
1772e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk        return -1;
1782e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk    }
1792e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk
18023f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    if (iovcnt <= 0) {
18116ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick        return 0;
18216ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick    }
18316ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick
1844389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn    int ret = 0;
1854389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn    int e = 0; // SLOGW and sigaction are not inert regarding errno
18623f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    int current = 0;
18723f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn
1884389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn    struct sigaction new_action, old_action;
1894389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn    memset(&new_action, 0, sizeof(new_action));
1904389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn    new_action.sa_handler = SIG_IGN;
1914389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn    sigaction(SIGPIPE, &new_action, &old_action);
1924389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn
19323f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn    for (;;) {
1944389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn        ssize_t rc = TEMP_FAILURE_RETRY(
1954389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn            writev(mSocket, iov + current, iovcnt - current));
1964389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn
197af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        if (rc > 0) {
19823f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn            size_t written = rc;
19923f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn            while ((current < iovcnt) && (written >= iov[current].iov_len)) {
20023f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn                written -= iov[current].iov_len;
20123f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn                current++;
20223f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn            }
20323f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn            if (current == iovcnt) {
20423f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn                break;
20523f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn            }
20623f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn            iov[current].iov_base = (char *)iov[current].iov_base + written;
20723f04107dcedcef22556c1f57502cdddbfa2663fMark Salyzyn            iov[current].iov_len -= written;
208af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner            continue;
209af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        }
210af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner
211af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        if (rc == 0) {
2124389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn            e = EIO;
2137e8529a8b528fd30586aa037f15a31b29582c537San Mehat            SLOGW("0 length write :(");
214af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner        } else {
2154389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn            e = errno;
2164389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn            SLOGW("write error (%s)", strerror(e));
217d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat        }
2184389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn        ret = -1;
2194389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn        break;
220fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    }
2214389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn
2224389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn    sigaction(SIGPIPE, &old_action, &new_action);
2234389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn
224f6b62d0a7d448e2685ef9afd934148943dc25a35Elliott Hughes    if (e != 0) {
2254df4dfedf6beef891d05d4e80704f5f4a594a885Bo Huang        errno = e;
226f6b62d0a7d448e2685ef9afd934148943dc25a35Elliott Hughes    }
2274389588e8ded66148d9e616aa20307cf25144460Mark Salyzyn    return ret;
228fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
229648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick
230648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrickvoid SocketClient::incRef() {
2314be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    pthread_mutex_lock(&mRefCountMutex);
2324be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    mRefCount++;
2334be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    pthread_mutex_unlock(&mRefCountMutex);
234648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick}
235648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick
2364be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrickbool SocketClient::decRef() {
2374be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    bool deleteSelf = false;
2384be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    pthread_mutex_lock(&mRefCountMutex);
2394be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    mRefCount--;
2404be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    if (mRefCount == 0) {
2414be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick        deleteSelf = true;
2424be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    } else if (mRefCount < 0) {
2434be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick        SLOGE("SocketClient refcount went negative!");
2444be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    }
2454be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    pthread_mutex_unlock(&mRefCountMutex);
2464be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    if (deleteSelf) {
2474be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick        delete this;
2484be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    }
2494be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick    return deleteSelf;
250648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick}
251