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