SocketClient.cpp revision 8702bb17f40022e970e8acd40b348d074e39afc7
1#include <alloca.h> 2#include <errno.h> 3#include <sys/socket.h> 4#include <sys/types.h> 5#include <pthread.h> 6#include <string.h> 7 8#define LOG_TAG "SocketClient" 9#include <cutils/log.h> 10 11#include <sysutils/SocketClient.h> 12 13SocketClient::SocketClient(int socket, bool owned) { 14 init(socket, owned, false); 15} 16 17SocketClient::SocketClient(int socket, bool owned, bool useCmdNum) { 18 init(socket, owned, useCmdNum); 19} 20 21void SocketClient::init(int socket, bool owned, bool useCmdNum) { 22 mSocket = socket; 23 mSocketOwned = owned; 24 mUseCmdNum = useCmdNum; 25 pthread_mutex_init(&mWriteMutex, NULL); 26 pthread_mutex_init(&mRefCountMutex, NULL); 27 mPid = -1; 28 mUid = -1; 29 mGid = -1; 30 mRefCount = 1; 31 mCmdNum = 0; 32 33 struct ucred creds; 34 socklen_t szCreds = sizeof(creds); 35 memset(&creds, 0, szCreds); 36 37 int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); 38 if (err == 0) { 39 mPid = creds.pid; 40 mUid = creds.uid; 41 mGid = creds.gid; 42 } 43} 44 45SocketClient::~SocketClient() 46{ 47 if (mSocketOwned) { 48 close(mSocket); 49 } 50} 51 52int SocketClient::sendMsg(int code, const char *msg, bool addErrno) { 53 return sendMsg(code, msg, addErrno, mUseCmdNum); 54} 55 56int SocketClient::sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum) { 57 char *buf; 58 int ret = 0; 59 60 if (addErrno) { 61 if (useCmdNum) { 62 ret = asprintf(&buf, "%d %d %s (%s)", code, getCmdNum(), msg, strerror(errno)); 63 } else { 64 ret = asprintf(&buf, "%d %s (%s)", code, msg, strerror(errno)); 65 } 66 } else { 67 if (useCmdNum) { 68 ret = asprintf(&buf, "%d %d %s", code, getCmdNum(), msg); 69 } else { 70 ret = asprintf(&buf, "%d %s", code, msg); 71 } 72 } 73 /* Send the zero-terminated message */ 74 if (ret != -1) { 75 ret = sendMsg(buf); 76 free(buf); 77 } 78 return ret; 79} 80 81int SocketClient::sendMsg(const char *msg) { 82 if (mSocket < 0) { 83 errno = EHOSTUNREACH; 84 return -1; 85 } 86 87 // Send the message including null character 88 if (sendData(msg, strlen(msg) + 1) != 0) { 89 SLOGW("Unable to send msg '%s'", msg); 90 return -1; 91 } 92 return 0; 93} 94 95int SocketClient::sendData(const void* data, int len) { 96 int rc = 0; 97 const char *p = (const char*) data; 98 int brtw = len; 99 100 if (len == 0) { 101 return 0; 102 } 103 104 pthread_mutex_lock(&mWriteMutex); 105 while (brtw > 0) { 106 rc = write(mSocket, p, brtw); 107 if (rc > 0) { 108 p += rc; 109 brtw -= rc; 110 continue; 111 } 112 113 if (rc < 0 && errno == EINTR) 114 continue; 115 116 pthread_mutex_unlock(&mWriteMutex); 117 if (rc == 0) { 118 SLOGW("0 length write :("); 119 errno = EIO; 120 } else { 121 SLOGW("write error (%s)", strerror(errno)); 122 } 123 return -1; 124 } 125 pthread_mutex_unlock(&mWriteMutex); 126 return 0; 127} 128 129void SocketClient::incRef() { 130 pthread_mutex_lock(&mRefCountMutex); 131 mRefCount++; 132 pthread_mutex_unlock(&mRefCountMutex); 133} 134 135bool SocketClient::decRef() { 136 bool deleteSelf = false; 137 pthread_mutex_lock(&mRefCountMutex); 138 mRefCount--; 139 if (mRefCount == 0) { 140 deleteSelf = true; 141 } else if (mRefCount < 0) { 142 SLOGE("SocketClient refcount went negative!"); 143 } 144 pthread_mutex_unlock(&mRefCountMutex); 145 if (deleteSelf) { 146 delete this; 147 } 148 return deleteSelf; 149} 150