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
SocketClient(int socket,bool owned)13 SocketClient::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
~SocketClient()36 SocketClient::~SocketClient()
37 {
38 if (mSocketOwned) {
39 close(mSocket);
40 }
41 }
42
sendMsg(int code,const char * msg,bool addErrno)43 int 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
sendMsg(const char * msg)66 int SocketClient::sendMsg(const char *msg) {
67 if (mSocket < 0) {
68 errno = EHOSTUNREACH;
69 return -1;
70 }
71
72 // Send the message including null character
73 if (sendData(msg, strlen(msg) + 1) != 0) {
74 SLOGW("Unable to send msg '%s'", msg);
75 return -1;
76 }
77 return 0;
78 }
79
sendData(const void * data,int len)80 int SocketClient::sendData(const void* data, int len) {
81 int rc = 0;
82 const char *p = (const char*) data;
83 int brtw = len;
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
incRef()114 void SocketClient::incRef() {
115 pthread_mutex_lock(&mRefCountMutex);
116 mRefCount++;
117 pthread_mutex_unlock(&mRefCountMutex);
118 }
119
decRef()120 bool 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