Remove unnecessary POLLOUT check.
[platform/core/appfw/message-port.git] / src / message_port_common.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
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 _GNU_SOURCE
18
19 #include <bundle.h>
20 #include <bundle_internal.h>
21 #include <pkgmgr-info.h>
22 #include <aul.h>
23
24 #include <sys/socket.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <openssl/md5.h>
30 #include <gio/gio.h>
31 #include <pthread.h>
32 #include <glib-unix.h>
33 #include <poll.h>
34
35 #include "message_port_log.h"
36 #include "message_port.h"
37 #include "message_port_common.h"
38
39 #define MAX_PACKAGE_STR_SIZE 512
40 #define MAX_RETRY_CNT 10
41
42 bool initialized_common;
43 GDBusConnection *gdbus_conn;
44 char *app_id;
45
46 static const int MAX_MESSAGE_SIZE = 16 * 1024;
47 static pthread_mutex_t _message_port_mutex = PTHREAD_MUTEX_INITIALIZER;
48
49 int write_socket(int fd,
50                 const char *buffer,
51                 unsigned int nbytes,
52                 unsigned int *bytes_write,
53                 int *sequence)
54 {
55         unsigned int left = nbytes;
56         ssize_t nb;
57         int retry_cnt = 0;
58
59         *sequence += 1;
60         *bytes_write = 0;
61
62         while (left && (retry_cnt < MAX_RETRY_CNT)) {
63                 nb = write(fd, buffer, left);
64                 if (nb == -1) {
65                         if (errno == EINTR) {
66                                 LOGW("write_socket: EINTR continue ...");
67                                 retry_cnt++;
68                                 continue;
69                         }
70                         LOGE("write_socket: ...error fd %d: errno %d\n", fd, errno);
71
72                         if (errno == EWOULDBLOCK || errno == EAGAIN)
73                                 return MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
74
75                         return MESSAGE_PORT_ERROR_IO_ERROR;
76                 }
77
78                 left -= nb;
79                 buffer += nb;
80                 *bytes_write += nb;
81                 retry_cnt = 0;
82         }
83
84         if (left != 0) {
85                 _LOGE("error fd %d: retry_cnt %d", fd, retry_cnt);
86                 return MESSAGE_PORT_ERROR_IO_ERROR;
87         }
88
89         return MESSAGE_PORT_ERROR_NONE;
90 }
91
92 int write_string_to_socket(int fd,
93                 const char *buffer,
94                 int string_len,
95                 unsigned int *bytes_write,
96                 int *sequence)
97 {
98         int ret;
99
100         ret = write_socket(fd, (char *)&string_len, sizeof(string_len),
101                         bytes_write, sequence);
102         if (ret != MESSAGE_PORT_ERROR_NONE) {
103                 _LOGE("write string_len fail");
104                 return ret;
105         }
106
107         if (string_len > 0) {
108                 ret = write_socket(fd, buffer, string_len, bytes_write, sequence);
109                 if (ret != MESSAGE_PORT_ERROR_NONE) {
110                         _LOGE("wirte buffer fail");
111                         return ret;
112                 }
113         } else {
114                 *sequence += 1;
115         }
116
117         return MESSAGE_PORT_ERROR_NONE;
118 }
119
120 int read_socket(int fd,
121                 char *buffer,
122                 unsigned int nbytes,
123                 unsigned int *bytes_read)
124 {
125         unsigned int left = nbytes;
126         ssize_t nb;
127         int retry_cnt = 0;
128         struct timespec TRY_SLEEP_TIME = { 0, 5 * 1000 * 1000 };
129
130         *bytes_read = 0;
131         while (left && (retry_cnt < MAX_RETRY_CNT)) {
132                 nb = read(fd, buffer, left);
133                 if (nb == 0) {
134                         LOGE("read_socket: ...read EOF, socket closed %d: nb %zd\n", fd, nb);
135                         return MESSAGE_PORT_ERROR_IO_ERROR;
136                 } else if (nb == -1) {
137                         /*  wrt(nodejs) could change socket to none-blocking socket :-( */
138                         if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
139                                 LOGW("read_socket: %d , sleep and retry ...", errno);
140                                 retry_cnt++;
141                                 nanosleep(&TRY_SLEEP_TIME, 0);
142                                 TRY_SLEEP_TIME.tv_nsec *= 2;
143                                 continue;
144                         }
145                         LOGE("read_socket: ...error fd %d: errno %d\n", fd, errno);
146                         return MESSAGE_PORT_ERROR_IO_ERROR;
147                 }
148
149                 left -= nb;
150                 buffer += nb;
151                 *bytes_read += nb;
152                 retry_cnt = 0;
153         }
154
155         if (left != 0) {
156                 _LOGE("error fd %d: retry_cnt %d", fd, retry_cnt);
157                 return MESSAGE_PORT_ERROR_IO_ERROR;
158         }
159
160         return MESSAGE_PORT_ERROR_NONE;
161 }
162
163 int read_string_from_socket(int fd, char **buffer, int *string_len)
164 {
165         unsigned int nb;
166         if (read_socket(fd, (char *)string_len, sizeof(*string_len), &nb) != MESSAGE_PORT_ERROR_NONE) {
167                 LOGE("read socket fail");
168                 return MESSAGE_PORT_ERROR_IO_ERROR;
169         }
170         if (*string_len > 0 && *string_len < MAX_MESSAGE_SIZE) {
171                 *buffer = (char *)calloc(*string_len, sizeof(char));
172                 if (*buffer == NULL) {
173                         LOGE("Out of memory.");
174                         return MESSAGE_PORT_ERROR_IO_ERROR;
175                 }
176                 if (read_socket(fd, *buffer, *string_len, &nb) != MESSAGE_PORT_ERROR_NONE) {
177                         LOGE("read socket fail");
178                         return MESSAGE_PORT_ERROR_IO_ERROR;
179                 }
180         } else {
181                 LOGE("Invalid string len %d", *string_len);
182                 return MESSAGE_PORT_ERROR_IO_ERROR;
183         }
184         return MESSAGE_PORT_ERROR_NONE;
185 }
186
187 static int __dbus_init(void)
188 {
189         bool ret = true;
190         GError *error = NULL;
191
192         gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
193         if (gdbus_conn == NULL) {
194                 if (error != NULL) {
195                         _LOGE("Failed to get dbus [%s]", error->message);
196                         g_error_free(error);
197                 }
198                 ret = false;
199         }
200
201         return ret;
202 }
203
204 bool initialize_common(void)
205 {
206
207 #if !GLIB_CHECK_VERSION(2, 35, 0)
208         g_type_init();
209 #endif
210
211         int pid = getpid();
212         int ret = 0;
213         char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
214
215         ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
216         retvm_if(ret != AUL_R_OK, false, "Failed to get the application ID: %d", ret);
217
218         app_id = strdup(buffer);
219         retvm_if(!app_id, false, "Malloc failed");
220         _LOGI("init : %s", app_id);
221
222         if (!__dbus_init())
223                 return false;
224         initialized_common = true;
225
226         return true;
227 }
228
229 bool is_preloaded(const char *local_appid, const char *remote_appid)
230 {
231         _LOGD("IsPreloaded");
232
233         bool preload_local = false;
234         bool preload_remote = false;
235
236         pkgmgrinfo_appinfo_h handle = NULL;
237         int ret = pkgmgrinfo_appinfo_get_usr_appinfo(local_appid, getuid(), &handle);
238         if (ret != PMINFO_R_OK) {
239                 _LOGE("Failed to get the appinfo. %d", ret);
240                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
241                 return false;
242         }
243         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_local);
244         if (ret != PMINFO_R_OK) {
245                 _LOGE("Failed to check the preloaded application. %d", ret);
246                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
247                 return false;
248         }
249         pkgmgrinfo_appinfo_destroy_appinfo(handle);
250
251         ret = pkgmgrinfo_appinfo_get_usr_appinfo(remote_appid, getuid(), &handle);
252         if (ret != PMINFO_R_OK) {
253                 _LOGE("Failed to get the appinfo. %d", ret);
254                 return false;
255         }
256         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_remote);
257         if (ret != PMINFO_R_OK) {
258                 _LOGE("Failed to check the preloaded application. %d", ret);
259                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
260                 return false;
261         }
262
263         if (preload_local && preload_remote) {
264                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
265                 return true;
266         }
267         pkgmgrinfo_appinfo_destroy_appinfo(handle);
268         return false;
269 }
270
271 int check_certificate(const char *local_appid, const char *remote_appid)
272 {
273         _LOGD("CheckCertificate");
274
275         pkgmgrinfo_cert_compare_result_type_e res;
276         int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(local_appid, remote_appid, getuid(), &res);
277         if (ret < 0) {
278                 _LOGE(":CheckCertificate() Failed");
279                 return MESSAGE_PORT_ERROR_IO_ERROR;
280         }
281         if (res != PMINFO_CERT_COMPARE_MATCH) {
282                 _LOGE("CheckCertificate() Failed : MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH");
283                 return MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH;
284         }
285
286         return MESSAGE_PORT_ERROR_NONE;
287 }
288
289 char *get_encoded_name(const char *remote_app_id, const char *port_name, bool is_trusted)
290 {
291
292         int prefix_len = strlen(MESSAGEPORT_BUS_NAME_PREFIX);
293         int postfix_len = 1;
294         char *postfix = is_trusted ? "1" : "0";
295
296         unsigned char c[MD5_DIGEST_LENGTH] = {0};
297         char *md5_interface = NULL;
298         char *temp;
299         int index = 0;
300         MD5_CTX mdContext;
301         int encoded_bus_name_len = prefix_len + postfix_len + (MD5_DIGEST_LENGTH * 2) + 2;
302         int bus_name_len = strlen(remote_app_id) + strlen(port_name) + 2;
303         char *bus_name = (char *)calloc(bus_name_len, sizeof(char));
304         if (bus_name == NULL) {
305                 _LOGE("bus_name calloc failed");
306                 return 0;
307         }
308
309         snprintf(bus_name, bus_name_len, "%s_%s", remote_app_id, port_name);
310
311         MD5_Init(&mdContext);
312         MD5_Update(&mdContext, bus_name, bus_name_len);
313         MD5_Final(c, &mdContext);
314
315         md5_interface = (char *)calloc(encoded_bus_name_len , sizeof(char));
316         if (md5_interface == NULL) {
317                 if (bus_name)
318                         free(bus_name);
319
320                 _LOGE("md5_interface calloc failed!!");
321                 return 0;
322         }
323
324         snprintf(md5_interface, encoded_bus_name_len, "%s", MESSAGEPORT_BUS_NAME_PREFIX);
325         temp = md5_interface;
326         temp += prefix_len;
327
328         for (index = 0; index < MD5_DIGEST_LENGTH; index++) {
329                 snprintf(temp, 3, "%02x", c[index]);
330                 temp += 2;
331         }
332
333         if (postfix && postfix_len > 0)
334                 snprintf(temp, encoded_bus_name_len - (temp - md5_interface), "%s", postfix);
335         if (bus_name)
336                 free(bus_name);
337
338         _LOGD("encoded_bus_name : %s ", md5_interface);
339
340         return md5_interface;
341 }
342
343 void message_port_lock_mutex()
344 {
345         pthread_mutex_lock(&_message_port_mutex);
346 }
347
348 void message_port_unlock_mutex()
349 {
350         pthread_mutex_unlock(&_message_port_mutex);
351 }