Fix improper errno handling
[platform/core/multimedia/libmm-sound.git] / mm_sound_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 <stdlib.h>
23 #include <unistd.h>
24 #include <mm_debug.h>
25 #include <sys/socket.h>
26 #include <sys/un.h>
27 #include "include/mm_sound.h"
28 #include "include/mm_sound_common.h"
29 #include "include/mm_sound_focus_socket.h"
30
31 #define _FILL_SOCKET_PARAM(x_param, x_func_name, x_pid) \
32 do { \
33         MMSOUND_STRNCPY(x_param.func_name, x_func_name, MM_SOUND_NAME_NUM); \
34         x_param.pid = x_pid; \
35 } while (0) \
36
37 #define _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id) \
38 do { \
39         _FILL_SOCKET_PARAM(x_param, x_func_name, x_pid); \
40         x_param.handle_id = x_id; \
41 } while (0) \
42
43 #define FILL_SOCKET_PARAM_REGISTER(x_param, x_func_name, x_pid, x_stream_type) \
44 do { \
45         _FILL_SOCKET_PARAM(x_param, x_func_name, x_pid); \
46         MMSOUND_STRNCPY(x_param.stream_type, x_stream_type, MM_SOUND_NAME_NUM); \
47 } while (0) \
48
49 #define FILL_SOCKET_PARAM_UNREGISTER(x_param, x_func_name, x_pid, x_id) \
50 do { \
51         _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id); \
52 } while (0) \
53
54 #define FILL_SOCKET_PARAM_ADD_WATCH(x_param, x_func_name, x_pid, x_focus_type) \
55 do { \
56         _FILL_SOCKET_PARAM(x_param, x_func_name, x_pid); \
57         x_param.focus_type = x_focus_type; \
58 } while (0) \
59
60 #define FILL_SOCKET_PARAM_REMOVE_WATCH(x_param, x_func_name, x_pid, x_id) \
61 do { \
62         _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id); \
63 } while (0) \
64
65 #define FILL_SOCKET_PARAM_SET_REACQUISITION(x_param, x_func_name, x_pid, x_id, x_reacquisition) \
66 do { \
67         _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id); \
68         x_param.reacquisition = x_reacquisition; \
69 } while (0) \
70
71 #define FILL_SOCKET_PARAM_DELIVER(x_param, x_func_name, x_pid, x_src_id, x_dst_id, x_focus_type) \
72 do { \
73         _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_src_id); \
74         x_param.handle_id_dst = x_dst_id; \
75         x_param.focus_type = x_focus_type; \
76 } while (0) \
77
78 #define FILL_SOCKET_PARAM_GET_ACQUIRED(x_param, x_func_name, x_focus_type) \
79 do { \
80         MMSOUND_STRNCPY(x_param.func_name, x_func_name, MM_SOUND_NAME_NUM); \
81         x_param.focus_type = x_focus_type; \
82 } while (0) \
83
84 #define FILL_SOCKET_PARAM(x_param, x_func_name, x_pid, x_id, x_focus_type, x_option, x_ext_info, x_is_in_thread) \
85 do { \
86         _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id); \
87         x_param.focus_type = x_focus_type; \
88         x_param.option = x_option; \
89         MMSOUND_STRNCPY(x_param.ext_info, x_ext_info, MM_SOUND_NAME_NUM); \
90         x_param.is_in_thread = x_is_in_thread; \
91 } while (0) \
92
93 static int _get_client_socket_fd(int *fd)
94 {
95         int socket_fd;
96         char str_error[128] = {'\0',};
97
98         if (fd == NULL) {
99                 debug_error("input param fd is null");
100                 return MM_ERROR_INVALID_ARGUMENT;
101         }
102
103         socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
104         if (socket_fd < 0) {
105                 strerror_r(errno, str_error, sizeof(str_error));
106                 debug_error("failed to socket(), err: %s", str_error);
107                 return MM_ERROR_SOUND_INTERNAL;
108         }
109
110         debug_log("focus client socket fd[%d]", socket_fd);
111
112         *fd = socket_fd;
113
114         return MM_ERROR_NONE;
115 }
116
117 static int _connect_socket_fd(int fd)
118 {
119         struct sockaddr_un addr_un;
120         char str_error[128] = {'\0',};
121
122         if (fd < 0) {
123                 debug_error("invalid fd[%d]", fd);
124                 return MM_ERROR_INVALID_ARGUMENT;
125         }
126
127         memset(&addr_un, 0, sizeof(addr_un));
128         addr_un.sun_family = AF_UNIX;
129         strncpy(addr_un.sun_path, FOCUS_SERVER_SOCK, sizeof(addr_un.sun_path));
130
131         if (connect(fd, (struct sockaddr *)&addr_un, sizeof(addr_un)) < 0) {
132                 strerror_r(errno, str_error, sizeof(str_error));
133                 debug_error("failed to connect() to %s, err: %s", addr_un.sun_path, str_error);
134                 return MM_ERROR_SOUND_INTERNAL;
135         }
136
137         debug_log("connected successfully, fd[%d]", fd);
138
139         return MM_ERROR_NONE;
140 }
141
142 static int _send_data_to_server(int fd, _mm_sound_focus_socket_param_t *data, _mm_sound_focus_socket_result_t *result)
143 {
144         char str_error[MAX_ERROR_LEN] = {'\0',};
145         int rval = 0;
146
147         if (fd < 0 || data == NULL) {
148                 debug_error("invalid parameter, fd[%d], data[%p]", fd, data);
149                 return MM_ERROR_INVALID_ARGUMENT;
150         }
151
152         if (write(fd, data, sizeof(_mm_sound_focus_socket_param_t)) < 0) {
153                 strerror_r(errno, str_error, sizeof(str_error));
154                 debug_error("failed to write(), err: %s", str_error);
155                 return MM_ERROR_SOUND_INTERNAL;
156         }
157
158         /* return message from server */
159         if ((rval = read(fd, result, sizeof(_mm_sound_focus_socket_result_t))) < 0) {
160                 strerror_r(errno, str_error, sizeof(str_error));
161                 debug_error("failed to read(), err: %s", str_error);
162                 return MM_ERROR_SOUND_INTERNAL;
163         }
164
165         debug_log("func_name[%s], rval[%d], ret[0x%x]", data->func_name, rval, result->ret);
166
167         return result->ret;
168 }
169
170 EXPORT_API
171 int mm_sound_focus_socket_register(int pid, const char *stream_type, int *client_fd, int *server_fd)
172 {
173         int ret = MM_ERROR_NONE;
174         _mm_sound_focus_socket_param_t data;
175         _mm_sound_focus_socket_result_t result;
176
177         debug_fenter();
178
179         if (!stream_type || !client_fd || !server_fd)
180                 return MM_ERROR_INVALID_ARGUMENT;
181
182         if ((ret = _get_client_socket_fd(client_fd))) {
183                 debug_error("failed to _get_client_socket_fd()");
184                 return MM_ERROR_SOUND_INTERNAL;
185         }
186         if ((ret = _connect_socket_fd(*client_fd))) {
187                 debug_error("failed to _connect_socket_fd()");
188                 close(*client_fd);
189                 return MM_ERROR_SOUND_INTERNAL;
190         }
191
192         /* get accepted fd from server */
193         memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
194         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
195         FILL_SOCKET_PARAM_REGISTER(data, FOCUS_FUNC_NAME_REGISTER, pid, stream_type);
196         if ((ret = _send_data_to_server(*client_fd, &data, &result))) {
197                 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
198                 close(*client_fd);
199                 return ret;
200         }
201
202         debug_msg("CONNECTED : client fd[%d], server fd[%d]", *client_fd, result.handle_id);
203         *server_fd = result.handle_id;
204
205         debug_fleave();
206
207         return ret;
208 }
209
210 EXPORT_API
211 int mm_sound_focus_socket_unregister(int pid, int client_fd, int server_fd)
212 {
213         int ret = MM_ERROR_NONE;
214         _mm_sound_focus_socket_param_t data;
215         _mm_sound_focus_socket_result_t result;
216
217         debug_fenter();
218
219         debug_msg("DISCONNECTING : client fd[%d], server fd[%d]", client_fd, server_fd);
220
221         memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
222         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
223         FILL_SOCKET_PARAM_UNREGISTER(data, FOCUS_FUNC_NAME_UNREGISTER, pid, server_fd);
224         if ((ret = _send_data_to_server(client_fd, &data, &result)))
225                 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
226
227         close(client_fd);
228
229         debug_fleave();
230
231         return ret;
232 }
233
234 EXPORT_API
235 int mm_sound_focus_socket_add_watch_cb(int pid, mm_sound_focus_type_e focus_type, int *client_fd, int *server_fd)
236 {
237         int ret = MM_ERROR_NONE;
238         _mm_sound_focus_socket_param_t data;
239         _mm_sound_focus_socket_result_t result;
240
241         debug_fenter();
242
243         if (!client_fd || !server_fd)
244                 return MM_ERROR_INVALID_ARGUMENT;
245
246         if ((ret = _get_client_socket_fd(client_fd))) {
247                 debug_error("failed to _get_client_socket_fd()");
248                 return MM_ERROR_SOUND_INTERNAL;
249         }
250         if ((ret = _connect_socket_fd(*client_fd))) {
251                 debug_error("failed to _connect_socket_fd()");
252                 close(*client_fd);
253                 return MM_ERROR_SOUND_INTERNAL;
254         }
255
256         /* get accepted fd from server */
257         memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
258         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
259         FILL_SOCKET_PARAM_ADD_WATCH(data, FOCUS_FUNC_NAME_ADD_WATCH, pid, focus_type);
260         if ((ret = _send_data_to_server(*client_fd, &data, &result))) {
261                 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
262                 close(*client_fd);
263                 return ret;
264         }
265
266         debug_msg("ADDED WATCH CB : client fd[%d], server fd[%d]", *client_fd, result.handle_id);
267         *server_fd = result.handle_id;
268
269         debug_fleave();
270
271         return ret;
272 }
273
274 EXPORT_API
275 int mm_sound_focus_socket_remove_watch_cb(int pid, int client_fd, int server_fd)
276 {
277         int ret = MM_ERROR_NONE;
278         _mm_sound_focus_socket_param_t data;
279         _mm_sound_focus_socket_result_t result;
280
281         debug_fenter();
282
283         debug_msg("REMOVING WATCH CB : client fd[%d], server fd[%d]", client_fd, server_fd);
284
285         memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
286         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
287         FILL_SOCKET_PARAM_REMOVE_WATCH(data, FOCUS_FUNC_NAME_REMOVE_WATCH, pid, server_fd);
288         if ((ret = _send_data_to_server(client_fd, &data, &result)))
289                 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
290
291         close(client_fd);
292
293         debug_fleave();
294
295         return ret;
296 }
297
298 EXPORT_API
299 int mm_sound_focus_socket_acquire(int pid, int client_fd, int server_fd, mm_sound_focus_type_e focus_type, int option, const char *ext_info, bool is_in_thread)
300 {
301         int ret = MM_ERROR_NONE;
302         _mm_sound_focus_socket_param_t data;
303         _mm_sound_focus_socket_result_t result;
304
305         debug_fenter();
306
307         if (pid <= 0 || client_fd < 0 || server_fd < 0 || option < 0) {
308                 debug_error("invalid parameter, pid[%d], fd[%d/%d], option[%d]",
309                                         pid, client_fd, server_fd, option);
310                 return MM_ERROR_INVALID_ARGUMENT;
311         }
312         if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
313                 debug_error("focus type[%d] is not valid", focus_type);
314                 return MM_ERROR_INVALID_ARGUMENT;
315         }
316
317         memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
318         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
319         FILL_SOCKET_PARAM(data, FOCUS_FUNC_NAME_ACQUIRE, pid, server_fd, focus_type,
320                                         option, ext_info, is_in_thread);
321
322         if ((ret = _send_data_to_server(client_fd, &data, &result)))
323                 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
324
325         debug_fleave();
326
327         return ret;
328 }
329
330 EXPORT_API
331 int mm_sound_focus_socket_release(int pid, int client_fd, int server_fd, mm_sound_focus_type_e focus_type, int option, const char *ext_info, bool is_in_thread)
332 {
333         int ret = MM_ERROR_NONE;
334         _mm_sound_focus_socket_param_t data;
335         _mm_sound_focus_socket_result_t result;
336
337         debug_fenter();
338
339         if (pid <= 0 || client_fd < 0 || server_fd < 0 || option < 0) {
340                 debug_error("invalid parameter, pid[%d], fd[%d/%d], option[%d]",
341                                         pid, client_fd, server_fd, option);
342                 return MM_ERROR_INVALID_ARGUMENT;
343         }
344         if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
345                 debug_error("focus type is not valid");
346                 return MM_ERROR_INVALID_ARGUMENT;
347         }
348
349         memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
350         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
351         FILL_SOCKET_PARAM(data, FOCUS_FUNC_NAME_RELEASE, pid, server_fd, focus_type,
352                                         option, ext_info, is_in_thread);
353
354         if ((ret = _send_data_to_server(client_fd, &data, &result)))
355                 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
356
357         debug_fleave();
358
359         return ret;
360 }
361
362
363 EXPORT_API
364 int mm_sound_focus_socket_set_reacquisition(int pid, int client_fd, int server_fd, bool reacquisition)
365 {
366         int ret = MM_ERROR_NONE;
367         _mm_sound_focus_socket_param_t data;
368         _mm_sound_focus_socket_result_t result;
369
370         debug_fenter();
371
372         if (pid <= 0 || client_fd < 0 || server_fd < 0) {
373                 debug_error("invalid parameter, pid[%d], fd[%d/%d]", pid, client_fd, server_fd);
374                 return MM_ERROR_INVALID_ARGUMENT;
375         }
376
377         memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
378         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
379         FILL_SOCKET_PARAM_SET_REACQUISITION(data, FOCUS_FUNC_NAME_SET_REACQUISITON, pid, server_fd, reacquisition);
380
381         if ((ret = _send_data_to_server(client_fd, &data, &result)))
382                 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
383
384         debug_fleave();
385
386         return ret;
387 }
388
389 EXPORT_API
390 int mm_sound_focus_socket_deliver(int pid, int src_client_fd, int src_server_fd, int dst_client_fd, int dst_server_fd, mm_sound_focus_type_e focus_type)
391 {
392         int ret = MM_ERROR_NONE;
393         _mm_sound_focus_socket_param_t data;
394         _mm_sound_focus_socket_result_t result;
395
396         debug_fenter();
397
398         if (pid <= 0 || src_client_fd < 0 || src_server_fd < 0 || dst_client_fd < 0 || dst_server_fd < 0) {
399                 debug_error("invalid parameter, pid[%d], src_fd[%d/%d], dst_fd[%d/%d]",
400                                         pid, src_client_fd, src_server_fd, dst_client_fd, dst_server_fd);
401                 return MM_ERROR_INVALID_ARGUMENT;
402         }
403
404         memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
405         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
406         FILL_SOCKET_PARAM_DELIVER(data, FOCUS_FUNC_NAME_DELIVER, pid, src_server_fd, dst_server_fd, focus_type);
407
408         if ((ret = _send_data_to_server(dst_client_fd, &data, &result)))
409                 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
410
411         debug_fleave();
412
413         return ret;
414 }
415
416 EXPORT_API
417 int mm_sound_focus_socket_get_acquired_focus_stream_type(mm_sound_focus_type_e focus_type, char **stream_type, int *option, char **ext_info)
418 {
419         int ret = MM_ERROR_NONE;
420         int fd = 0;
421         _mm_sound_focus_socket_param_t data;
422         _mm_sound_focus_socket_result_t result;
423
424         debug_fenter();
425
426         if (!stream_type) {
427                 debug_error("invalid parameter, stream_type[%p]", stream_type);
428                 return MM_ERROR_INVALID_ARGUMENT;
429         }
430         if ((ret = _get_client_socket_fd(&fd))) {
431                 debug_error("failed to _get_client_socket_fd()");
432                 return MM_ERROR_SOUND_INTERNAL;
433         }
434         if ((ret = _connect_socket_fd(fd))) {
435                 debug_error("failed to _connect_socket_fd()");
436                 close(fd);
437                 return MM_ERROR_SOUND_INTERNAL;
438         }
439
440         memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
441         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
442         FILL_SOCKET_PARAM_GET_ACQUIRED(data, FOCUS_FUNC_NAME_GET_ACQUIRED_INFO, focus_type);
443
444         if ((ret = _send_data_to_server(fd, &data, &result))) {
445                 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
446                 close(fd);
447                 return ret;
448         }
449
450         debug_msg("stream_type[%s], option[%d], ext_info[%s]", result.stream_type, result.option, result.ext_info);
451
452         *stream_type = strdup(result.stream_type);
453         *ext_info = strdup(result.ext_info);
454         *option = result.option;
455
456         close(fd);
457
458         debug_fleave();
459
460         return ret;
461 }