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> 77bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun#include <arpa/inet.h> 8fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 9fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#define LOG_TAG "SocketClient" 10fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <cutils/log.h> 11fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 12fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <sysutils/SocketClient.h> 13fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 148702bb17f40022e970e8acd40b348d074e39afc7Robert GreenwaltSocketClient::SocketClient(int socket, bool owned) { 158702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt init(socket, owned, false); 168702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt} 178702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt 188702bb17f40022e970e8acd40b348d074e39afc7Robert GreenwaltSocketClient::SocketClient(int socket, bool owned, bool useCmdNum) { 198702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt init(socket, owned, useCmdNum); 208702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt} 218702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt 228702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwaltvoid SocketClient::init(int socket, bool owned, bool useCmdNum) { 238702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mSocket = socket; 248702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mSocketOwned = owned; 258702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mUseCmdNum = useCmdNum; 26fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_init(&mWriteMutex, NULL); 27648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick pthread_mutex_init(&mRefCountMutex, NULL); 288702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mPid = -1; 298702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mUid = -1; 308702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mGid = -1; 318702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mRefCount = 1; 328702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mCmdNum = 0; 3330abb7234de2a9caa1add4b00a189436f0b24560Kenny Root 3430abb7234de2a9caa1add4b00a189436f0b24560Kenny Root struct ucred creds; 3530abb7234de2a9caa1add4b00a189436f0b24560Kenny Root socklen_t szCreds = sizeof(creds); 3630abb7234de2a9caa1add4b00a189436f0b24560Kenny Root memset(&creds, 0, szCreds); 3730abb7234de2a9caa1add4b00a189436f0b24560Kenny Root 3830abb7234de2a9caa1add4b00a189436f0b24560Kenny Root int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); 3930abb7234de2a9caa1add4b00a189436f0b24560Kenny Root if (err == 0) { 4030abb7234de2a9caa1add4b00a189436f0b24560Kenny Root mPid = creds.pid; 4130abb7234de2a9caa1add4b00a189436f0b24560Kenny Root mUid = creds.uid; 4230abb7234de2a9caa1add4b00a189436f0b24560Kenny Root mGid = creds.gid; 4330abb7234de2a9caa1add4b00a189436f0b24560Kenny Root } 44fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 45fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 464520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu WangSocketClient::~SocketClient() 474520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang{ 484520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang if (mSocketOwned) { 494520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang close(mSocket); 504520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang } 514520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang} 524520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang 53db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(int code, const char *msg, bool addErrno) { 548702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt return sendMsg(code, msg, addErrno, mUseCmdNum); 558702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt} 568702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt 578702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwaltint SocketClient::sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum) { 58d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat char *buf; 598702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt int ret = 0; 6003f0d27f6c49530a91402ed42f8ca4b2fda04b9fSan Mehat 61d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat if (addErrno) { 628702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt if (useCmdNum) { 638702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt ret = asprintf(&buf, "%d %d %s (%s)", code, getCmdNum(), msg, strerror(errno)); 648702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt } else { 658702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt ret = asprintf(&buf, "%d %s (%s)", code, msg, strerror(errno)); 668702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt } 67d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat } else { 688702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt if (useCmdNum) { 698702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt ret = asprintf(&buf, "%d %d %s", code, getCmdNum(), msg); 708702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt } else { 718702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt ret = asprintf(&buf, "%d %s", code, msg); 728702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt } 73d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat } 74af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner /* Send the zero-terminated message */ 758702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt if (ret != -1) { 768702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt ret = sendMsg(buf); 778702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt free(buf); 788702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt } 798702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt return ret; 80d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat} 81d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat 827599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt/** send 3-digit code, null, binary-length, binary data */ 837bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendBinaryMsg(int code, const void *data, int len) { 847bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 857599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt /* 4 bytes for the code & null + 4 bytes for the len */ 867599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt char buf[8]; 877bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun /* Write the code */ 887599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt snprintf(buf, 4, "%.3d", code); 897bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun /* Write the len */ 907bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun uint32_t tmp = htonl(len); 917599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt memcpy(buf + 4, &tmp, sizeof(uint32_t)); 927bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 937bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun pthread_mutex_lock(&mWriteMutex); 947bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun int result = sendDataLocked(buf, sizeof(buf)); 957bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun if (result == 0 && len > 0) { 967bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun result = sendDataLocked(data, len); 977bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun } 987bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun pthread_mutex_unlock(&mWriteMutex); 997bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1007bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun return result; 1017bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun} 1027bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1037bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun// Sends the code (c-string null-terminated). 1047bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendCode(int code) { 1057599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt char buf[4]; 1067599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt snprintf(buf, sizeof(buf), "%.3d", code); 1077599bfcf13cf022333338b7a87aaddae69c48d73Robert Greenwalt return sendData(buf, sizeof(buf)); 1087bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun} 1097bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 110594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwaltchar *SocketClient::quoteArg(const char *arg) { 111594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt int len = strlen(arg); 112594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt char *result = (char *)malloc(len * 2 + 3); 113594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt char *current = result; 114594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt const char *end = arg + len; 115544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li char *oldresult; 116544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li 117544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li if(result == NULL) { 118544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li SLOGW("malloc error (%s)", strerror(errno)); 119544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li return NULL; 120544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li } 121594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt 122594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = '"'; 123594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt while (arg < end) { 124594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt switch (*arg) { 125594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt case '\\': 126594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt case '"': 127594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = '\\'; // fallthrough 128594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt default: 129594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = *(arg++); 130594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt } 131594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt } 132594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = '"'; 133594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = '\0'; 134544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li oldresult = result; // save pointer in case realloc fails 135594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt result = (char *)realloc(result, current-result); 136544a7f7a36cb9434505fe5cdc9e79d16937ac23fHong-Mei Li return result ? result : oldresult; 137594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt} 138594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt 139594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt 140db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(const char *msg) { 141c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat // Send the message including null character 1428c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick if (sendData(msg, strlen(msg) + 1) != 0) { 1438c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick SLOGW("Unable to send msg '%s'", msg); 1448c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick return -1; 1458c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick } 1468c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick return 0; 1478c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick} 1488c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick 1497bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendData(const void *data, int len) { 1507bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1517bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun pthread_mutex_lock(&mWriteMutex); 1527bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun int rc = sendDataLocked(data, len); 1537bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun pthread_mutex_unlock(&mWriteMutex); 1547bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1557bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun return rc; 1567bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun} 1577bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1587bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendDataLocked(const void *data, int len) { 159d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat int rc = 0; 1608c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick const char *p = (const char*) data; 1618c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick int brtw = len; 162d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat 1632e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk if (mSocket < 0) { 1642e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk errno = EHOSTUNREACH; 1652e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk return -1; 1662e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk } 1672e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4Mattias Falk 16816ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick if (len == 0) { 16916ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick return 0; 17016ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick } 17116ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick 1728c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick while (brtw > 0) { 1736ac770fc52595b8230c3286d7707c85b003aeac1Selim Gurun rc = send(mSocket, p, brtw, MSG_NOSIGNAL); 174af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc > 0) { 175af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner p += rc; 176af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner brtw -= rc; 177af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner continue; 178af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner } 179af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner 180af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc < 0 && errno == EINTR) 181af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner continue; 182af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner 183af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc == 0) { 1847e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGW("0 length write :("); 185d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat errno = EIO; 186af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner } else { 187af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner SLOGW("write error (%s)", strerror(errno)); 188d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat } 189af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner return -1; 190fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 191fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return 0; 192fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 193648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick 194648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrickvoid SocketClient::incRef() { 1954be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_lock(&mRefCountMutex); 1964be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick mRefCount++; 1974be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_unlock(&mRefCountMutex); 198648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick} 199648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick 2004be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrickbool SocketClient::decRef() { 2014be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick bool deleteSelf = false; 2024be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_lock(&mRefCountMutex); 2034be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick mRefCount--; 2044be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick if (mRefCount == 0) { 2054be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick deleteSelf = true; 2064be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } else if (mRefCount < 0) { 2074be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick SLOGE("SocketClient refcount went negative!"); 2084be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } 2094be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_unlock(&mRefCountMutex); 2104be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick if (deleteSelf) { 2114be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick delete this; 2124be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } 2134be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick return deleteSelf; 214648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick} 215