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