SocketClient.cpp revision 6ac770fc52595b8230c3286d7707c85b003aeac1
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 110db017545796747115b8797f03e662b0f398a7c7bSan Mehatint SocketClient::sendMsg(const char *msg) { 111fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (mSocket < 0) { 112fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat errno = EHOSTUNREACH; 113fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 114fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 115fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 116c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat // Send the message including null character 1178c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick if (sendData(msg, strlen(msg) + 1) != 0) { 1188c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick SLOGW("Unable to send msg '%s'", msg); 1198c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick return -1; 1208c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick } 1218c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick return 0; 1228c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick} 1238c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick 1247bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendData(const void *data, int len) { 1257bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1267bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun pthread_mutex_lock(&mWriteMutex); 1277bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun int rc = sendDataLocked(data, len); 1287bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun pthread_mutex_unlock(&mWriteMutex); 1297bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1307bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun return rc; 1317bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun} 1327bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurun 1337bf4c45f842ded6d6ad6b2d80e052ddf56969723Selim Gurunint SocketClient::sendDataLocked(const void *data, int len) { 134d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat int rc = 0; 1358c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick const char *p = (const char*) data; 1368c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick int brtw = len; 137d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat 13816ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick if (len == 0) { 13916ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick return 0; 14016ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick } 14116ae478af46100a435c2875afa020721a59a411aBrad Fitzpatrick 1428c5669f9f9a228efebf4059fd4ceace5cece578bBrad Fitzpatrick while (brtw > 0) { 1436ac770fc52595b8230c3286d7707c85b003aeac1Selim Gurun rc = send(mSocket, p, brtw, MSG_NOSIGNAL); 144af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc > 0) { 145af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner p += rc; 146af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner brtw -= rc; 147af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner continue; 148af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner } 149af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner 150af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc < 0 && errno == EINTR) 151af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner continue; 152af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner 153af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner if (rc == 0) { 1547e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGW("0 length write :("); 155d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat errno = EIO; 156af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner } else { 157af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner SLOGW("write error (%s)", strerror(errno)); 158d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat } 159af61509b50bc110b0c7c4691e37873cc0987ab5cDavid 'Digit' Turner return -1; 160fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 161fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return 0; 162fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 163648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick 164648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrickvoid SocketClient::incRef() { 1654be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_lock(&mRefCountMutex); 1664be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick mRefCount++; 1674be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_unlock(&mRefCountMutex); 168648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick} 169648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick 1704be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrickbool SocketClient::decRef() { 1714be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick bool deleteSelf = false; 1724be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_lock(&mRefCountMutex); 1734be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick mRefCount--; 1744be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick if (mRefCount == 0) { 1754be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick deleteSelf = true; 1764be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } else if (mRefCount < 0) { 1774be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick SLOGE("SocketClient refcount went negative!"); 1784be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } 1794be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick pthread_mutex_unlock(&mRefCountMutex); 1804be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick if (deleteSelf) { 1814be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick delete this; 1824be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick } 1834be4e69f0128b7d9b0a29651ef4b79d806ae3ce7Brad Fitzpatrick return deleteSelf; 184648ebad883e7825353c841950dd7d78664c238e6Brad Fitzpatrick} 185