SocketClient.cpp revision 2e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4
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 134520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu WangSocketClient::SocketClient(int socket, bool owned) 1430abb7234de2a9caa1add4b00a189436f0b24560Kenny Root : mSocket(socket) 154520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang , mSocketOwned(owned) 1630abb7234de2a9caa1add4b00a189436f0b24560Kenny Root , mPid(-1) 1730abb7234de2a9caa1add4b00a189436f0b24560Kenny Root , mUid(-1) 1830abb7234de2a9caa1add4b00a189436f0b24560Kenny Root , mGid(-1) 19648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick , mRefCount(1) 2030abb7234de2a9caa1add4b00a189436f0b24560Kenny Root{ 21fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_init(&mWriteMutex, NULL); 22648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick pthread_mutex_init(&mRefCountMutex, NULL); 2330abb7234de2a9caa1add4b00a189436f0b24560Kenny Root 2430abb7234de2a9caa1add4b00a189436f0b24560Kenny Root struct ucred creds; 2530abb7234de2a9caa1add4b00a189436f0b24560Kenny Root socklen_t szCreds = sizeof(creds); 2630abb7234de2a9caa1add4b00a189436f0b24560Kenny Root memset(&creds, 0, szCreds); 2730abb7234de2a9caa1add4b00a189436f0b24560Kenny Root 2830abb7234de2a9caa1add4b00a189436f0b24560Kenny Root int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); 2930abb7234de2a9caa1add4b00a189436f0b24560Kenny Root if (err == 0) { 3030abb7234de2a9caa1add4b00a189436f0b24560Kenny Root mPid = creds.pid; 3130abb7234de2a9caa1add4b00a189436f0b24560Kenny Root mUid = creds.uid; 3230abb7234de2a9caa1add4b00a189436f0b24560Kenny Root mGid = creds.gid; 3330abb7234de2a9caa1add4b00a189436f0b24560Kenny Root } 34fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 35fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 364520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu WangSocketClient::~SocketClient() 374520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang{ 384520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang if (mSocketOwned) { 394520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang close(mSocket); 404520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang } 414520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang} 424520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang 43db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(int code, const char *msg, bool addErrno) { 44d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat char *buf; 45af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner const char* arg; 46af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner const char* fmt; 47af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner char tmp[1]; 48af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner int len; 4903f0d27f6c49530a91402ed42f8ca4b2fda04b9fSan Mehat 50d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat if (addErrno) { 51af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner fmt = "%.3d %s (%s)"; 52af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner arg = strerror(errno); 53d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat } else { 54af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner fmt = "%.3d %s"; 55af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner arg = NULL; 56d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat } 57af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner /* Measure length of required buffer */ 58af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner len = snprintf(tmp, sizeof tmp, fmt, code, msg, arg); 59af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner /* Allocate in the stack, then write to it */ 60af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner buf = (char*)alloca(len+1); 61af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner snprintf(buf, len+1, fmt, code, msg, arg); 62af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner /* Send the zero-terminated message */ 63d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat return sendMsg(buf); 64d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat} 65d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat 66db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(const char *msg) { 67c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat // Send the message including null character 688c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick if (sendData(msg, strlen(msg) + 1) != 0) { 698c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick SLOGW("Unable to send msg '%s'", msg); 708c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick return -1; 718c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick } 728c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick return 0; 738c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick} 748c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick 758c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrickint SocketClient::sendData(const void* data, int len) { 76d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat int rc = 0; 778c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick const char *p = (const char*) data; 788c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick int brtw = len; 79d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat 802e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk if (mSocket < 0) { 812e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk errno = EHOSTUNREACH; 822e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk return -1; 832e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk } 842e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk 8516ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick if (len == 0) { 8616ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick return 0; 8716ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick } 8816ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick 89fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mWriteMutex); 908c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick while (brtw > 0) { 91af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner rc = write(mSocket, p, brtw); 92af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc > 0) { 93af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner p += rc; 94af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner brtw -= rc; 95af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner continue; 96af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner } 97af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner 98af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc < 0 && errno == EINTR) 99af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner continue; 100af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner 101af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner pthread_mutex_unlock(&mWriteMutex); 102af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc == 0) { 1037e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGW("0 length write :("); 104d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat errno = EIO; 105af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner } else { 106af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner SLOGW("write error (%s)", strerror(errno)); 107d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat } 108af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner return -1; 109fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 110fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mWriteMutex); 111fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return 0; 112fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 113648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick 114648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrickvoid SocketClient::incRef() { 1154be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_lock(&mRefCountMutex); 1164be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick mRefCount++; 1174be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_unlock(&mRefCountMutex); 118648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick} 119648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick 1204be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrickbool SocketClient::decRef() { 1214be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick bool deleteSelf = false; 1224be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_lock(&mRefCountMutex); 1234be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick mRefCount--; 1244be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick if (mRefCount == 0) { 1254be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick deleteSelf = true; 1264be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } else if (mRefCount < 0) { 1274be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick SLOGE("SocketClient refcount went negative!"); 1284be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } 1294be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_unlock(&mRefCountMutex); 1304be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick if (deleteSelf) { 1314be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick delete this; 1324be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } 1334be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick return deleteSelf; 134648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick} 135