blob: 971f90821794f6d5998e5ce41feb4379c9f00887 [file] [log] [blame]
Mark Salyzyn66ce3e02016-09-28 10:07:20 -07001/*
2 * Copyright (C) 2009-2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "SocketClient"
18
San Mehatfa644ff2009-05-08 11:15:53 -070019#include <alloca.h>
Mark Salyzyn66ce3e02016-09-28 10:07:20 -070020#include <arpa/inet.h>
San Mehatfa644ff2009-05-08 11:15:53 -070021#include <errno.h>
Elliott Hughesa744b052015-01-28 11:37:57 -080022#include <malloc.h>
San Mehatfa644ff2009-05-08 11:15:53 -070023#include <pthread.h>
Mark Salyzyn43895882014-01-29 11:25:01 -080024#include <signal.h>
San Mehatd7680662009-05-12 11:16:59 -070025#include <string.h>
Mark Salyzyn43895882014-01-29 11:25:01 -080026#include <sys/socket.h>
27#include <sys/types.h>
Mark Salyzyncfd5b082016-10-17 14:28:00 -070028#include <unistd.h>
San Mehatfa644ff2009-05-08 11:15:53 -070029
Mark Salyzyncfd5b082016-10-17 14:28:00 -070030#include <log/log.h>
San Mehatfa644ff2009-05-08 11:15:53 -070031#include <sysutils/SocketClient.h>
32
Robert Greenwalt8702bb12012-02-07 12:23:14 -080033SocketClient::SocketClient(int socket, bool owned) {
34 init(socket, owned, false);
35}
36
37SocketClient::SocketClient(int socket, bool owned, bool useCmdNum) {
38 init(socket, owned, useCmdNum);
39}
40
41void SocketClient::init(int socket, bool owned, bool useCmdNum) {
42 mSocket = socket;
43 mSocketOwned = owned;
44 mUseCmdNum = useCmdNum;
San Mehatfa644ff2009-05-08 11:15:53 -070045 pthread_mutex_init(&mWriteMutex, NULL);
Brad Fitzpatrick648ebad2011-03-17 15:41:20 -070046 pthread_mutex_init(&mRefCountMutex, NULL);
Robert Greenwalt8702bb12012-02-07 12:23:14 -080047 mPid = -1;
48 mUid = -1;
49 mGid = -1;
50 mRefCount = 1;
51 mCmdNum = 0;
Kenny Root30abb722010-09-14 14:26:12 -070052
53 struct ucred creds;
54 socklen_t szCreds = sizeof(creds);
55 memset(&creds, 0, szCreds);
56
57 int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
58 if (err == 0) {
59 mPid = creds.pid;
60 mUid = creds.uid;
61 mGid = creds.gid;
62 }
San Mehatfa644ff2009-05-08 11:15:53 -070063}
64
Mark Salyzyn43895882014-01-29 11:25:01 -080065SocketClient::~SocketClient() {
Xianzhu Wang45202462011-09-29 12:59:55 +080066 if (mSocketOwned) {
67 close(mSocket);
68 }
69}
70
San Mehatdb017542009-05-20 15:27:14 -070071int SocketClient::sendMsg(int code, const char *msg, bool addErrno) {
Robert Greenwalt8702bb12012-02-07 12:23:14 -080072 return sendMsg(code, msg, addErrno, mUseCmdNum);
73}
74
75int SocketClient::sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum) {
San Mehatd7680662009-05-12 11:16:59 -070076 char *buf;
Robert Greenwalt8702bb12012-02-07 12:23:14 -080077 int ret = 0;
San Mehat03f0d272009-05-26 15:18:25 -070078
San Mehatd7680662009-05-12 11:16:59 -070079 if (addErrno) {
Robert Greenwalt8702bb12012-02-07 12:23:14 -080080 if (useCmdNum) {
81 ret = asprintf(&buf, "%d %d %s (%s)", code, getCmdNum(), msg, strerror(errno));
82 } else {
83 ret = asprintf(&buf, "%d %s (%s)", code, msg, strerror(errno));
84 }
San Mehatd7680662009-05-12 11:16:59 -070085 } else {
Robert Greenwalt8702bb12012-02-07 12:23:14 -080086 if (useCmdNum) {
87 ret = asprintf(&buf, "%d %d %s", code, getCmdNum(), msg);
88 } else {
89 ret = asprintf(&buf, "%d %s", code, msg);
90 }
San Mehatd7680662009-05-12 11:16:59 -070091 }
Mark Salyzyn23f04102012-01-24 20:30:10 -080092 // Send the zero-terminated message
Robert Greenwalt8702bb12012-02-07 12:23:14 -080093 if (ret != -1) {
94 ret = sendMsg(buf);
95 free(buf);
96 }
97 return ret;
San Mehatd7680662009-05-12 11:16:59 -070098}
99
Mark Salyzyn23f04102012-01-24 20:30:10 -0800100// send 3-digit code, null, binary-length, binary data
Selim Gurun7bf4c452012-02-27 16:04:37 -0800101int SocketClient::sendBinaryMsg(int code, const void *data, int len) {
102
Mark Salyzyn23f04102012-01-24 20:30:10 -0800103 // 4 bytes for the code & null + 4 bytes for the len
Robert Greenwalt7599bfc2012-03-08 16:10:06 -0800104 char buf[8];
Mark Salyzyn23f04102012-01-24 20:30:10 -0800105 // Write the code
Robert Greenwalt7599bfc2012-03-08 16:10:06 -0800106 snprintf(buf, 4, "%.3d", code);
Mark Salyzyn23f04102012-01-24 20:30:10 -0800107 // Write the len
Selim Gurun7bf4c452012-02-27 16:04:37 -0800108 uint32_t tmp = htonl(len);
Robert Greenwalt7599bfc2012-03-08 16:10:06 -0800109 memcpy(buf + 4, &tmp, sizeof(uint32_t));
Selim Gurun7bf4c452012-02-27 16:04:37 -0800110
Mark Salyzyn23f04102012-01-24 20:30:10 -0800111 struct iovec vec[2];
112 vec[0].iov_base = (void *) buf;
113 vec[0].iov_len = sizeof(buf);
114 vec[1].iov_base = (void *) data;
115 vec[1].iov_len = len;
116
Selim Gurun7bf4c452012-02-27 16:04:37 -0800117 pthread_mutex_lock(&mWriteMutex);
Mark Salyzyn23f04102012-01-24 20:30:10 -0800118 int result = sendDataLockedv(vec, (len > 0) ? 2 : 1);
Selim Gurun7bf4c452012-02-27 16:04:37 -0800119 pthread_mutex_unlock(&mWriteMutex);
120
121 return result;
122}
123
124// Sends the code (c-string null-terminated).
125int SocketClient::sendCode(int code) {
Robert Greenwalt7599bfc2012-03-08 16:10:06 -0800126 char buf[4];
127 snprintf(buf, sizeof(buf), "%.3d", code);
128 return sendData(buf, sizeof(buf));
Selim Gurun7bf4c452012-02-27 16:04:37 -0800129}
130
Robert Greenwalt59494772012-04-20 15:21:07 -0700131char *SocketClient::quoteArg(const char *arg) {
132 int len = strlen(arg);
133 char *result = (char *)malloc(len * 2 + 3);
134 char *current = result;
135 const char *end = arg + len;
Hong-Mei Li544a7f72013-04-01 11:24:44 +0800136 char *oldresult;
137
138 if(result == NULL) {
139 SLOGW("malloc error (%s)", strerror(errno));
140 return NULL;
141 }
Robert Greenwalt59494772012-04-20 15:21:07 -0700142
143 *(current++) = '"';
144 while (arg < end) {
145 switch (*arg) {
146 case '\\':
147 case '"':
148 *(current++) = '\\'; // fallthrough
149 default:
150 *(current++) = *(arg++);
151 }
152 }
153 *(current++) = '"';
154 *(current++) = '\0';
Hong-Mei Li544a7f72013-04-01 11:24:44 +0800155 oldresult = result; // save pointer in case realloc fails
Robert Greenwalt59494772012-04-20 15:21:07 -0700156 result = (char *)realloc(result, current-result);
Hong-Mei Li544a7f72013-04-01 11:24:44 +0800157 return result ? result : oldresult;
Robert Greenwalt59494772012-04-20 15:21:07 -0700158}
159
160
San Mehatdb017542009-05-20 15:27:14 -0700161int SocketClient::sendMsg(const char *msg) {
San Mehatc73a3a52009-06-15 14:06:03 -0700162 // Send the message including null character
Brad Fitzpatrick8c5669f2010-10-27 10:23:16 -0700163 if (sendData(msg, strlen(msg) + 1) != 0) {
164 SLOGW("Unable to send msg '%s'", msg);
165 return -1;
166 }
167 return 0;
168}
169
Selim Gurun7bf4c452012-02-27 16:04:37 -0800170int SocketClient::sendData(const void *data, int len) {
Mark Salyzyn23f04102012-01-24 20:30:10 -0800171 struct iovec vec[1];
172 vec[0].iov_base = (void *) data;
173 vec[0].iov_len = len;
Selim Gurun7bf4c452012-02-27 16:04:37 -0800174
175 pthread_mutex_lock(&mWriteMutex);
Mark Salyzyn23f04102012-01-24 20:30:10 -0800176 int rc = sendDataLockedv(vec, 1);
Selim Gurun7bf4c452012-02-27 16:04:37 -0800177 pthread_mutex_unlock(&mWriteMutex);
178
179 return rc;
180}
181
Mark Salyzyn23f04102012-01-24 20:30:10 -0800182int SocketClient::sendDatav(struct iovec *iov, int iovcnt) {
183 pthread_mutex_lock(&mWriteMutex);
184 int rc = sendDataLockedv(iov, iovcnt);
185 pthread_mutex_unlock(&mWriteMutex);
186
187 return rc;
188}
189
190int SocketClient::sendDataLockedv(struct iovec *iov, int iovcnt) {
San Mehatd7680662009-05-12 11:16:59 -0700191
Mattias Falk2e5fcd02011-05-13 16:25:38 +0200192 if (mSocket < 0) {
193 errno = EHOSTUNREACH;
194 return -1;
195 }
196
Mark Salyzyn23f04102012-01-24 20:30:10 -0800197 if (iovcnt <= 0) {
Brad Fitzpatrick16ae4782010-11-02 10:55:52 -0700198 return 0;
199 }
200
Mark Salyzyn43895882014-01-29 11:25:01 -0800201 int ret = 0;
202 int e = 0; // SLOGW and sigaction are not inert regarding errno
Mark Salyzyn23f04102012-01-24 20:30:10 -0800203 int current = 0;
204
Mark Salyzyn43895882014-01-29 11:25:01 -0800205 struct sigaction new_action, old_action;
206 memset(&new_action, 0, sizeof(new_action));
207 new_action.sa_handler = SIG_IGN;
208 sigaction(SIGPIPE, &new_action, &old_action);
209
Mark Salyzyn23f04102012-01-24 20:30:10 -0800210 for (;;) {
Mark Salyzyn43895882014-01-29 11:25:01 -0800211 ssize_t rc = TEMP_FAILURE_RETRY(
212 writev(mSocket, iov + current, iovcnt - current));
213
David 'Digit' Turneraf615092011-01-17 02:34:15 +0100214 if (rc > 0) {
Mark Salyzyn23f04102012-01-24 20:30:10 -0800215 size_t written = rc;
216 while ((current < iovcnt) && (written >= iov[current].iov_len)) {
217 written -= iov[current].iov_len;
218 current++;
219 }
220 if (current == iovcnt) {
221 break;
222 }
223 iov[current].iov_base = (char *)iov[current].iov_base + written;
224 iov[current].iov_len -= written;
David 'Digit' Turneraf615092011-01-17 02:34:15 +0100225 continue;
226 }
227
David 'Digit' Turneraf615092011-01-17 02:34:15 +0100228 if (rc == 0) {
Mark Salyzyn43895882014-01-29 11:25:01 -0800229 e = EIO;
San Mehat7e8529a2010-03-25 09:31:42 -0700230 SLOGW("0 length write :(");
David 'Digit' Turneraf615092011-01-17 02:34:15 +0100231 } else {
Mark Salyzyn43895882014-01-29 11:25:01 -0800232 e = errno;
233 SLOGW("write error (%s)", strerror(e));
San Mehatd7680662009-05-12 11:16:59 -0700234 }
Mark Salyzyn43895882014-01-29 11:25:01 -0800235 ret = -1;
236 break;
San Mehatfa644ff2009-05-08 11:15:53 -0700237 }
Mark Salyzyn43895882014-01-29 11:25:01 -0800238
239 sigaction(SIGPIPE, &old_action, &new_action);
240
Elliott Hughesf6b62d02014-11-10 15:50:30 -0800241 if (e != 0) {
Bo Huang4df4dfe2014-09-29 14:54:02 +0800242 errno = e;
Elliott Hughesf6b62d02014-11-10 15:50:30 -0800243 }
Mark Salyzyn43895882014-01-29 11:25:01 -0800244 return ret;
San Mehatfa644ff2009-05-08 11:15:53 -0700245}
Brad Fitzpatrick648ebad2011-03-17 15:41:20 -0700246
247void SocketClient::incRef() {
Brad Fitzpatrick4be4e692011-03-17 17:14:46 -0700248 pthread_mutex_lock(&mRefCountMutex);
249 mRefCount++;
250 pthread_mutex_unlock(&mRefCountMutex);
Brad Fitzpatrick648ebad2011-03-17 15:41:20 -0700251}
252
Brad Fitzpatrick4be4e692011-03-17 17:14:46 -0700253bool SocketClient::decRef() {
254 bool deleteSelf = false;
255 pthread_mutex_lock(&mRefCountMutex);
256 mRefCount--;
257 if (mRefCount == 0) {
258 deleteSelf = true;
259 } else if (mRefCount < 0) {
260 SLOGE("SocketClient refcount went negative!");
261 }
262 pthread_mutex_unlock(&mRefCountMutex);
263 if (deleteSelf) {
264 delete this;
265 }
266 return deleteSelf;
Brad Fitzpatrick648ebad2011-03-17 15:41:20 -0700267}