Fix coverity issues
[platform/core/multimedia/libmm-sound.git] / focus_server / mm_sound_mgr_focus_socket.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Sangchul Lee <sc11.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <mm_error.h>
27 #include <mm_debug.h>
28
29 #include <gio/gio.h>
30
31 #include <sys/socket.h>
32 #include <sys/un.h>
33
34 #include "../include/mm_sound_focus_socket.h"
35 #include "include/mm_sound_mgr_focus.h"
36 #include "include/mm_sound_mgr_focus_ipc.h"
37
38 static pthread_t g_focus_ready_thread_id = 0;
39
40 typedef int (*focus_function_handler) (int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
41 static int handle_register_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
42 static int handle_unregister_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
43 static int handle_add_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
44 static int handle_remove_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
45 static int handle_acquire_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
46 static int handle_release_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
47 static int handle_set_focus_reacquisition(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
48 static int handle_deliver_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
49 static int handle_get_acquired_focus_info(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
50
51 enum {
52         FOCUS_FUNCTION_REGISTER,
53         FOCUS_FUNCTION_UNREGISTER,
54         FOCUS_FUNCTION_ADD_WATCH,
55         FOCUS_FUNCTION_REMOVE_WATCH,
56         FOCUS_FUNCTION_ACQUIRE,
57         FOCUS_FUNCTION_RELEASE,
58         FOCUS_FUNCTION_SET_REACQUISITION,
59         FOCUS_FUNCTION_DELIVER,
60         FOCUS_FUNCTION_GET_ACQUIRED_INFO,
61         FOCUS_FUNCTION_MAX,
62 };
63
64 typedef struct mm_sound_focus_function_intf {
65         const char *name;
66         focus_function_handler handler;
67 } mm_sound_focus_function_intf_t;
68
69 static mm_sound_focus_function_intf_t functions[FOCUS_FUNCTION_MAX] = {
70         [FOCUS_FUNCTION_REGISTER] = {
71                 .name = FOCUS_FUNC_NAME_REGISTER,
72                 .handler = handle_register_focus
73         },
74         [FOCUS_FUNCTION_UNREGISTER] = {
75                 .name = FOCUS_FUNC_NAME_UNREGISTER,
76                 .handler = handle_unregister_focus
77         },
78         [FOCUS_FUNCTION_ADD_WATCH] = {
79                 .name = FOCUS_FUNC_NAME_ADD_WATCH,
80                 .handler = handle_add_watch_focus
81         },
82         [FOCUS_FUNCTION_REMOVE_WATCH] = {
83                 .name = FOCUS_FUNC_NAME_REMOVE_WATCH,
84                 .handler = handle_remove_watch_focus
85         },
86         [FOCUS_FUNCTION_ACQUIRE] = {
87                 .name = FOCUS_FUNC_NAME_ACQUIRE,
88                 .handler = handle_acquire_focus
89         },
90         [FOCUS_FUNCTION_RELEASE] = {
91                 .name = FOCUS_FUNC_NAME_RELEASE,
92                 .handler = handle_release_focus
93         },
94         [FOCUS_FUNCTION_SET_REACQUISITION] = {
95                 .name = FOCUS_FUNC_NAME_SET_REACQUISITON,
96                 .handler = handle_set_focus_reacquisition
97         },
98         [FOCUS_FUNCTION_DELIVER] = {
99                 .name = FOCUS_FUNC_NAME_DELIVER,
100                 .handler = handle_deliver_focus
101         },
102         [FOCUS_FUNCTION_GET_ACQUIRED_INFO] = {
103                 .name = FOCUS_FUNC_NAME_GET_ACQUIRED_INFO,
104                 .handler = handle_get_acquired_focus_info
105         }
106 };
107
108 static int handle_register_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
109 {
110         int ret = MM_ERROR_NONE;
111
112         debug_fenter();
113
114         ret = __mm_sound_mgr_focus_ipc_register_focus(param->pid, fd, param->stream_type);
115         result->handle_id = fd;
116
117         debug_fleave();
118
119         return ret;
120 }
121
122 static int handle_unregister_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
123 {
124         int ret = MM_ERROR_NONE;
125
126         debug_fenter();
127
128         if (fd != param->handle_id) {
129                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
130                 return MM_ERROR_SOUND_INTERNAL;
131         }
132         ret = __mm_sound_mgr_focus_ipc_unregister_focus(param->pid, param->handle_id);
133
134         debug_fleave();
135
136         return ret;
137 }
138
139 static int handle_add_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
140 {
141         int ret = MM_ERROR_NONE;
142
143         debug_fenter();
144
145         ret = __mm_sound_mgr_focus_ipc_add_watch_node(param->pid, fd, param->focus_type);
146         result->handle_id = fd;
147
148         debug_fleave();
149
150         return ret;
151 }
152
153 static int handle_remove_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
154 {
155         int ret = MM_ERROR_NONE;
156
157         debug_fenter();
158
159         if (fd != param->handle_id) {
160                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
161                 return MM_ERROR_SOUND_INTERNAL;
162         }
163         ret = __mm_sound_mgr_focus_ipc_remove_watch_node(param->pid, param->handle_id);
164
165         debug_fleave();
166
167         return ret;
168 }
169
170 static int handle_acquire_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
171 {
172         int ret = MM_ERROR_NONE;
173
174         debug_fenter();
175
176         if (fd != param->handle_id) {
177                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
178                 return MM_ERROR_SOUND_INTERNAL;
179         }
180         ret = __mm_sound_mgr_focus_ipc_acquire_focus(param->pid, param->handle_id, param->focus_type,
181                                                                                                 param->option, param->ext_info, true);
182
183         debug_fleave();
184
185         return ret;
186 }
187
188 static int handle_release_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
189 {
190         int ret = MM_ERROR_NONE;
191
192         debug_fenter();
193
194         if (fd != param->handle_id) {
195                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
196                 return MM_ERROR_SOUND_INTERNAL;
197         }
198         ret = __mm_sound_mgr_focus_ipc_release_focus(param->pid, param->handle_id, param->focus_type,
199                                                                                                 param->option, param->ext_info, true);
200
201         debug_fleave();
202
203         return ret;
204 }
205
206 static int handle_set_focus_reacquisition(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
207 {
208         int ret = MM_ERROR_NONE;
209
210         debug_fenter();
211
212         if (fd != param->handle_id) {
213                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
214                 return MM_ERROR_SOUND_INTERNAL;
215         }
216         ret = __mm_sound_mgr_focus_ipc_set_focus_reacquisition(param->pid, param->handle_id, param->reacquisition);
217
218         debug_fleave();
219
220         return ret;
221 }
222
223 static int handle_deliver_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
224 {
225         int ret = MM_ERROR_NONE;
226
227         debug_fenter();
228
229         ret = __mm_sound_mgr_focus_ipc_deliver_focus(param->pid, param->handle_id, param->handle_id_dst, param->focus_type);
230
231         debug_fleave();
232
233         return ret;
234 }
235
236 static int handle_get_acquired_focus_info(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
237 {
238         int ret = MM_ERROR_NONE;
239         char *res_stream_type = NULL;
240         char *res_ext_info = NULL;
241
242         debug_fenter();
243
244         if (!result) {
245                 debug_error("invalid arguments, result[%p]", result);
246                 return MM_ERROR_INVALID_ARGUMENT;
247         }
248
249         ret = __mm_sound_mgr_focus_ipc_get_acquired_focus_stream_type(param->focus_type, &res_stream_type, &result->option, &res_ext_info);
250         if (ret == MM_ERROR_NONE) {
251                 MMSOUND_STRNCPY(result->stream_type, res_stream_type, MM_SOUND_NAME_NUM);
252                 MMSOUND_STRNCPY(result->ext_info, res_ext_info, MM_SOUND_NAME_NUM);
253         }
254
255         debug_fleave();
256
257         return ret;
258 }
259
260 static int focus_functions_handler(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
261 {
262         int i = 0;
263         int ret = MM_ERROR_NONE;
264
265         if (param == NULL)
266                 return MM_ERROR_INVALID_ARGUMENT;
267
268         debug_log("fd[%d], param[%p], function_name[%s]", fd, param, param->func_name);
269
270         for (i = 0; i < FOCUS_FUNCTION_MAX; i++) {
271                 if (!strncmp(param->func_name, functions[i].name, MAX_ERROR_LEN))
272                         ret = functions[i].handler(fd, param, result);
273         }
274
275         return ret;
276 }
277
278 static bool need_to_exit(const char *func_name)
279 {
280         if (!strncmp(func_name, FOCUS_FUNC_NAME_UNREGISTER, MM_SOUND_NAME_NUM) ||
281                 !strncmp(func_name, FOCUS_FUNC_NAME_REMOVE_WATCH, MM_SOUND_NAME_NUM) ||
282                 !strncmp(func_name, FOCUS_FUNC_NAME_GET_ACQUIRED_INFO, MM_SOUND_NAME_NUM))
283                 return true;
284
285         return false;
286 }
287
288 static void* work_thread_func(void *data)
289 {
290         int accepted_fd = -1;
291         char str_error[MAX_ERROR_LEN] = {'\0',};
292         _mm_sound_focus_socket_param_t read_data;
293         _mm_sound_focus_socket_result_t result;
294         int rval = 0;
295
296         if (data == NULL) {
297                 debug_error("invalid data");
298                 pthread_exit(NULL);
299         }
300
301         debug_fenter();
302
303         accepted_fd = (int)(data);
304
305         do {
306                 memset(&read_data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
307                 if ((rval = read(accepted_fd, &read_data, sizeof(_mm_sound_focus_socket_param_t))) < 0) {
308                         strerror_r(errno, str_error, sizeof(str_error));
309                         debug_error("failed to read(), err: %s", str_error);
310
311                 } else if (rval == sizeof(_mm_sound_focus_socket_param_t)) {
312                         int ret = MM_ERROR_NONE;
313
314                         debug_log("data read successfully, command[%s], pid[%d]",
315                                         read_data.func_name, read_data.pid);
316
317                         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
318                         if ((ret = focus_functions_handler(accepted_fd, &read_data, &result)))
319                                 debug_error("failed to focus_function_handler(), err[0x%x]", ret);
320                         result.ret = ret;
321
322                         /* send result */
323                         if (write(accepted_fd, &result, sizeof(_mm_sound_focus_socket_result_t)) < 0) {
324                                 strerror_r(errno, str_error, sizeof(str_error));
325                                 debug_error("failed to write(), err: %s", str_error);
326                         }
327
328                         if (need_to_exit(read_data.func_name))
329                                 goto LEAVE;
330                 } else {
331                         debug_error("failed to read(), read size mismatched, rval(%d), expect size(%d)",
332                                                 rval, sizeof(_mm_sound_focus_socket_param_t));
333                         goto LEAVE;
334                 }
335         } while (1);
336
337 LEAVE:
338         debug_fleave();
339         debug_log("now close fd[%d]", accepted_fd);
340         /* clean-up FD and focus node */
341         mm_sound_mgr_focus_emergent_exit_by_id(accepted_fd);
342         close(accepted_fd);
343         pthread_exit(NULL);
344 }
345
346 static void* ready_thread_func(void *data)
347 {
348         int fd = -1;
349         int accepted_fd = -1;
350         char str_error[MAX_ERROR_LEN] = {'\0',};
351         int ret = 0;
352         pthread_t focus_work_thread_id;
353         pthread_attr_t attr;
354
355         if (data == NULL) {
356                 debug_error("invalid data");
357                 pthread_exit(NULL);
358         }
359
360         debug_fenter();
361
362         ret = pthread_attr_init(&attr);
363         if (ret != 0) {
364                 debug_error("failed to init pthread attr, errno=%d", ret);
365                 goto LEAVE;
366         }
367
368         ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
369         if (ret != 0) {
370                 debug_error("failed to set detach state, errno=%d", ret);
371                 goto LEAVE;
372         }
373
374         fd = (int)data;
375
376         if (listen(fd, 5)) {
377                 strerror_r(errno, str_error, sizeof(str_error));
378                 debug_error("failed to listen(), err: %s", str_error);
379                 goto LEAVE;
380         }
381         debug_log("listen for fd [%d] success", fd);
382
383         do {
384                 accepted_fd = accept(fd, NULL, NULL);
385                 if (accepted_fd == -1) {
386                         strerror_r(errno, str_error, sizeof(str_error));
387                         debug_error("failed to accept(), err: %s", str_error);
388                         goto LEAVE;
389                 }
390
391                 debug_log("accepted fd [%d]", accepted_fd);
392
393                 if (pthread_create(&focus_work_thread_id, &attr, (void *)work_thread_func, (void *)accepted_fd)) {
394                         debug_error("failed to create work thread, accepted_fd(%d)", accepted_fd);
395                         goto LEAVE;
396                 }
397
398         } while (1);
399
400 LEAVE:
401         debug_fleave();
402         pthread_attr_destroy(&attr);
403         if (fd != -1)
404                 close(fd);
405         pthread_exit(NULL);
406 }
407
408 int MMSoundMgrFocusSocketInit(int *fd)
409 {
410         int socket_fd;
411         struct sockaddr_un addr_un;
412         char str_error[128] = {'\0',};
413
414         if (fd == NULL) {
415                 debug_error("input param fd is null");
416                 return MM_ERROR_INVALID_ARGUMENT;
417         }
418
419         socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
420         if (socket_fd < 0) {
421                 strerror_r(errno, str_error, sizeof(str_error));
422                 debug_error("failed to socket(), err: %s", str_error);
423                 goto LEAVE;
424         }
425
426         debug_log("focus server socket fd [%d]", socket_fd);
427
428         memset(&addr_un, 0, sizeof(addr_un));
429         addr_un.sun_family = AF_UNIX;
430         strncpy(addr_un.sun_path, FOCUS_SERVER_SOCK, sizeof(addr_un.sun_path));
431
432         if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
433                 strerror_r(errno, str_error, sizeof(str_error));
434                 debug_error("failed to bind(), err: %s", str_error);
435                 if (errno == EADDRINUSE) {
436                         unlink(FOCUS_SERVER_SOCK);
437                         debug_msg("unlink socket and bind again...");
438                         if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
439                                 strerror_r(errno, str_error, sizeof(str_error));
440                                 debug_error("failed to bind() again, err: %s", str_error);
441                                 goto LEAVE;
442                         }
443                 } else {
444                         goto LEAVE;
445                 }
446         }
447
448         debug_log("focus server socket binding success");
449
450         *fd = socket_fd;
451
452         debug_leave();
453
454         return MM_ERROR_NONE;
455
456 LEAVE:
457         if (socket_fd >= 0)
458                 close(socket_fd);
459
460         return MM_ERROR_SOUND_INTERNAL;
461 }
462
463 void MMSoundMgrFocusSocketFini(int fd)
464 {
465         debug_enter();
466
467         if (g_focus_ready_thread_id) {
468                 unlink(FOCUS_SERVER_SOCK);
469                 shutdown(fd, SHUT_RDWR);
470                 close(fd);
471                 pthread_join(g_focus_ready_thread_id, NULL);
472                 debug_msg("pthread join well");
473                 g_focus_ready_thread_id = 0;
474         }
475
476         debug_leave();
477 }
478
479 int MMSoundMgrFocusSocketReadyToWork(int fd)
480 {
481         debug_enter();
482
483         if (fd < 0) {
484                 debug_error("input param fd [%d] is not valid", fd);
485                 return MM_ERROR_INVALID_ARGUMENT;
486         }
487
488         debug_log("fd [%d]", fd);
489         if (pthread_create(&g_focus_ready_thread_id, NULL, (void *)ready_thread_func, (void *)fd)) {
490                 debug_error("failed to create ready thread");
491                 return MM_ERROR_SOUND_INTERNAL;
492         }
493
494         debug_leave();
495
496         return MM_ERROR_NONE;
497 }