SocketClient.cpp revision 2e5fcd08ac177e984ebf1fb05bab5dfcf296c5a4
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 : mSocket(socket) 15 , mSocketOwned(owned) 16 , mPid(-1) 17 , mUid(-1) 18 , mGid(-1) 19 , mRefCount(1) 20{ 21 pthread_mutex_init(&mWriteMutex, NULL); 22 pthread_mutex_init(&mRefCountMutex, NULL); 23 24 struct ucred creds; 25 socklen_t szCreds = sizeof(creds); 26 memset(&creds, 0, szCreds); 27 28 int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); 29 if (err == 0) { 30 mPid = creds.pid; 31 mUid = creds.uid; 32 mGid = creds.gid; 33 } 34} 35 36SocketClient::~SocketClient() 37{ 38 if (mSocketOwned) { 39 close(mSocket); 40 } 41} 42 43int SocketClient::sendMsg(int code, const char *msg, bool addErrno) { 44 char *buf; 45 const char* arg; 46 const char* fmt; 47 char tmp[1]; 48 int len; 49 50 if (addErrno) { 51 fmt = "%.3d %s (%s)"; 52 arg = strerror(errno); 53 } else { 54 fmt = "%.3d %s"; 55 arg = NULL; 56 } 57 /* Measure length of required buffer */ 58 len = snprintf(tmp, sizeof tmp, fmt, code, msg, arg); 59 /* Allocate in the stack, then write to it */ 60 buf = (char*)alloca(len+1); 61 snprintf(buf, len+1, fmt, code, msg, arg); 62 /* Send the zero-terminated message */ 63 return sendMsg(buf); 64} 65 66int SocketClient::sendMsg(const char *msg) { 67 // Send the message including null character 68 if (sendData(msg, strlen(msg) + 1) != 0) { 69 SLOGW("Unable to send msg '%s'", msg); 70 return -1; 71 } 72 return 0; 73} 74 75int SocketClient::sendData(const void* data, int len) { 76 int rc = 0; 77 const char *p = (const char*) data; 78 int brtw = len; 79 80 if (mSocket < 0) { 81 errno = EHOSTUNREACH; 82 return -1; 83 } 84 85 if (len == 0) { 86 return 0; 87 } 88 89 pthread_mutex_lock(&mWriteMutex); 90 while (brtw > 0) { 91 rc = write(mSocket, p, brtw); 92 if (rc > 0) { 93 p += rc; 94 brtw -= rc; 95 continue; 96 } 97 98 if (rc < 0 && errno == EINTR) 99 continue; 100 101 pthread_mutex_unlock(&mWriteMutex); 102 if (rc == 0) { 103 SLOGW("0 length write :("); 104 errno = EIO; 105 } else { 106 SLOGW("write error (%s)", strerror(errno)); 107 } 108 return -1; 109 } 110 pthread_mutex_unlock(&mWriteMutex); 111 return 0; 112} 113 114void SocketClient::incRef() { 115 pthread_mutex_lock(&mRefCountMutex); 116 mRefCount++; 117 pthread_mutex_unlock(&mRefCountMutex); 118} 119 120bool SocketClient::decRef() { 121 bool deleteSelf = false; 122 pthread_mutex_lock(&mRefCountMutex); 123 mRefCount--; 124 if (mRefCount == 0) { 125 deleteSelf = true; 126 } else if (mRefCount < 0) { 127 SLOGE("SocketClient refcount went negative!"); 128 } 129 pthread_mutex_unlock(&mRefCountMutex); 130 if (deleteSelf) { 131 delete this; 132 } 133 return deleteSelf; 134} 135