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; 115594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt 116594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = '"'; 117594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt while (arg < end) { 118594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt switch (*arg) { 119594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt case '\\': 120594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt case '"': 121594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = '\\'; // fallthrough 122594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt default: 123594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = *(arg++); 124594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt } 125594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt } 126594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = '"'; 127594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt *(current++) = '\0'; 128594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt result = (char *)realloc(result, current-result); 129594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt return result; 130594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt} 131594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt 132594947793c98e8e7f58f0e9b2cb962c9ef23adebRobert Greenwalt 133db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(const char *msg) { 134fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (mSocket < 0) { 135fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat errno = EHOSTUNREACH; 136fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 137fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 138fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 139c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat // Send the message including null character 1408c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick if (sendData(msg, strlen(msg) + 1) != 0) { 1418c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick SLOGW("Unable to send msg '%s'", msg); 1428c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick return -1; 1438c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick } 1448c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick return 0; 1458c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick} 1468c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick 1477bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendData(const void *data, int len) { 1487bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1497bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun pthread_mutex_lock(&mWriteMutex); 1507bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun int rc = sendDataLocked(data, len); 1517bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun pthread_mutex_unlock(&mWriteMutex); 1527bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1537bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun return rc; 1547bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun} 1557bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1567bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendDataLocked(const void *data, int len) { 157d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat int rc = 0; 1588c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick const char *p = (const char*) data; 1598c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick int brtw = len; 160d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat 16116ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick if (len == 0) { 16216ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick return 0; 16316ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick } 16416ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick 1658c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick while (brtw > 0) { 1666ac770fc52595b8230c3286d7707c85b003aeac1Selim Gurun rc = send(mSocket, p, brtw, MSG_NOSIGNAL); 167af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc > 0) { 168af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner p += rc; 169af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner brtw -= rc; 170af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner continue; 171af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner } 172af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner 173af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc < 0 && errno == EINTR) 174af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner continue; 175af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner 176af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc == 0) { 1777e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGW("0 length write :("); 178d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat errno = EIO; 179af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner } else { 180af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner SLOGW("write error (%s)", strerror(errno)); 181d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat } 182af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner return -1; 183fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 184fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return 0; 185fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 186648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick 187648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrickvoid SocketClient::incRef() { 1884be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_lock(&mRefCountMutex); 1894be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick mRefCount++; 1904be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_unlock(&mRefCountMutex); 191648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick} 192648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick 1934be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrickbool SocketClient::decRef() { 1944be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick bool deleteSelf = false; 1954be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_lock(&mRefCountMutex); 1964be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick mRefCount--; 1974be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick if (mRefCount == 0) { 1984be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick deleteSelf = true; 1994be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } else if (mRefCount < 0) { 2004be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick SLOGE("SocketClient refcount went negative!"); 2014be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } 2024be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_unlock(&mRefCountMutex); 2034be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick if (deleteSelf) { 2044be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick delete this; 2054be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } 2064be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick return deleteSelf; 207648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick} 208