Update IPC
[platform/core/uifw/stt.git] / server / sttd_dbus.c
1 /*
2 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd All Rights Reserved 
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14
15 #include <dbus/dbus.h>
16 #include <Ecore.h>
17
18 #include "sttd_main.h"
19 #include "sttd_dbus.h"
20 #include "sttd_client_data.h"
21 #include "sttd_dbus_server.h"
22 #include "stt_defs.h"
23
24 static DBusConnection* g_conn_sender = NULL;
25 static DBusConnection* g_conn_listener = NULL;
26
27 static Ecore_Fd_Handler* g_dbus_fd_handler = NULL;
28
29 static int g_waiting_time = 3000;
30
31
32 int sttdc_send_hello(int uid)
33 {
34         int pid = sttd_client_get_pid(uid);
35         if (0 > pid) {
36                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid");
37                 return STTD_ERROR_INVALID_PARAMETER;
38         }
39
40         char service_name[64];
41         memset(service_name, 0, 64);
42         snprintf(service_name, 64, "%s", STT_CLIENT_SERVICE_NAME);
43
44         char target_if_name[128];
45         snprintf(target_if_name, sizeof(target_if_name), "%s", STT_CLIENT_SERVICE_INTERFACE);
46
47         DBusMessage* msg = NULL;
48
49         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] Send hello message : uid(%d)", uid);
50
51         msg = dbus_message_new_method_call(
52                 service_name, 
53                 STT_CLIENT_SERVICE_OBJECT_PATH, 
54                 target_if_name, 
55                 STTD_METHOD_HELLO);
56
57         if (NULL == msg) {
58                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message");
59                 return STTD_ERROR_OUT_OF_MEMORY;
60         }
61
62         dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID);
63
64         DBusError err;
65         dbus_error_init(&err);
66         int result = -1;
67
68         DBusMessage* result_msg = NULL;
69         result_msg = dbus_connection_send_with_reply_and_block(g_conn_sender, msg, g_waiting_time, &err);
70         dbus_message_unref(msg);
71         if (dbus_error_is_set(&err)) {
72                 SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Send error (%s)", err.message);
73                 dbus_error_free(&err);
74         }
75
76         if (NULL != result_msg) {
77                 dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
78
79                 if (dbus_error_is_set(&err)) { 
80                         SLOG(LOG_ERROR, TAG_STTD, "[Dbus] Get arguments error (%s)\n", err.message);
81                         dbus_error_free(&err); 
82                         result = -1;
83                 }
84
85                 dbus_message_unref(result_msg);
86         } else {
87                 SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] Result message is NULL. Client is not available");
88         }
89
90         return result;
91 }
92
93 int sttdc_send_set_state(int uid, int state)
94 {
95         int pid = sttd_client_get_pid(uid);
96
97         if (0 > pid) {
98                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid");
99                 return -1;
100         }
101
102         char service_name[64];
103         memset(service_name, 0, 64);
104         snprintf(service_name, 64, "%s", STT_CLIENT_SERVICE_NAME);
105
106         char target_if_name[128];
107         snprintf(target_if_name, sizeof(target_if_name), "%s", STT_CLIENT_SERVICE_INTERFACE);
108
109         DBusMessage* msg;
110
111         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] Send change state message : uid(%d), state(%d)", uid, state);
112
113         msg = dbus_message_new_method_call(
114                 service_name,
115                 STT_CLIENT_SERVICE_OBJECT_PATH,
116                 target_if_name,
117                 STTD_METHOD_SET_STATE);
118
119         if (NULL == msg) {
120                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message");
121                 return -1;
122         }
123
124         dbus_message_append_args(msg,
125                 DBUS_TYPE_INT32, &uid,
126                 DBUS_TYPE_INT32, &state,
127                 DBUS_TYPE_INVALID);
128
129         dbus_message_set_no_reply(msg, TRUE);
130
131         if (!dbus_connection_send(g_conn_sender, msg, NULL)) {
132                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to send message : Out Of Memory !");
133         }
134         else {
135                 SLOG(LOG_DEBUG, TAG_STTD, "<<<< Send error message : uid(%d), state(%d)", uid, state);
136                 dbus_connection_flush(g_conn_sender);
137         }
138
139         dbus_connection_flush(g_conn_sender);
140         dbus_message_unref(msg);
141
142         return 0;
143 }
144 int sttdc_send_get_state(int uid, int* state)
145 {
146         int pid = sttd_client_get_pid(uid);
147
148         if (0 > pid) {
149                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid");
150                 return -1;
151         }
152
153         char service_name[64];
154         memset(service_name, 0, 64);
155         snprintf(service_name, 64, "%s", STT_CLIENT_SERVICE_NAME);
156
157         char target_if_name[128];
158         snprintf(target_if_name, sizeof(target_if_name), "%s", STT_CLIENT_SERVICE_INTERFACE);
159
160         DBusMessage* msg;
161
162         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] Send get state message : uid(%d)", uid);
163
164         msg = dbus_message_new_method_call(
165                 service_name, 
166                 STT_CLIENT_SERVICE_OBJECT_PATH, 
167                 target_if_name, 
168                 STTD_METHOD_GET_STATE);
169
170         if (NULL == msg) { 
171                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message"); 
172                 return -1;
173         }
174
175         dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID);
176
177         DBusError err;
178         dbus_error_init(&err);
179
180         DBusMessage* result_msg;
181         int tmp = -1;
182         int result = 0;
183
184         result_msg = dbus_connection_send_with_reply_and_block(g_conn_sender, msg, g_waiting_time, &err);
185         dbus_message_unref(msg);
186         if (dbus_error_is_set(&err)) {
187                 SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Send error (%s)", err.message);
188                 dbus_error_free(&err);
189         }
190
191         if (NULL != result_msg) {
192                 dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &tmp, DBUS_TYPE_INVALID);
193
194                 if (dbus_error_is_set(&err)) { 
195                         SLOG(LOG_ERROR, TAG_STTD, "[Dbus] Get arguments error (%s)\n", err.message);
196                         dbus_error_free(&err); 
197                         result = -1;
198                 } else {
199                         *state = tmp;
200                         result = 0;
201                 }
202
203                 dbus_message_unref(result_msg);
204         } else {
205                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus] Result message is NULL. Client is not available");
206                 result = -1;
207         }
208         
209         return result;
210 }
211
212 int sttdc_send_result(int uid, int event, const char** data, int data_count, const char* result_msg)
213 {
214         int pid = sttd_client_get_pid(uid);
215         if (0 > pid) {
216                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid" );
217                 return STTD_ERROR_INVALID_PARAMETER;
218         }
219
220         char service_name[64];
221         memset(service_name, 0, 64);
222         snprintf(service_name, 64, "%s", STT_CLIENT_SERVICE_NAME);
223
224         char target_if_name[128];
225         memset(target_if_name, 0, 128);
226         snprintf(target_if_name, sizeof(target_if_name), "%s", STT_CLIENT_SERVICE_INTERFACE);
227
228         DBusMessage* msg = NULL;
229         SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] send result signal : uid(%d), event(%d), result count(%d)", uid, event, data_count);
230
231         msg = dbus_message_new_method_call(
232                 service_name, 
233                 STT_CLIENT_SERVICE_OBJECT_PATH, 
234                 target_if_name, 
235                 STTD_METHOD_RESULT);
236
237         if (NULL == msg) {
238                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message");
239                 return STTD_ERROR_OUT_OF_MEMORY;
240         }
241
242         DBusMessageIter args;
243         dbus_message_iter_init_append(msg, &args);
244
245         /* Append uid & type */
246         dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &uid);
247
248         char* msg_temp;
249         dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &event);
250
251         /* Append result msg */
252         if (NULL == result_msg) {
253                 msg_temp = strdup("None");
254                 dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &msg_temp);
255                 SLOG(LOG_WARN, TAG_STTD, "[Dbus] result message is NULL"); 
256                 free(msg_temp);
257         } else {
258                 SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] result message(%s)", result_msg ); 
259                 dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(result_msg));
260         }
261         
262         /* Append result size */
263         if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(data_count))) {
264                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus] response message : Fail to append result size"); 
265                 return -1;
266         }
267
268         int i;
269         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] result size (%d)", data_count); 
270         for (i = 0;i < data_count;i++) {
271                 if (NULL != data[i]) {
272                         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] result (%d, %s)", i, data[i] ); 
273
274                         if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &data[i])) {
275                                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus] response message : Fail to append result data");
276                                 dbus_message_unref(msg);
277                                 return STTD_ERROR_OPERATION_FAILED;
278                         }
279                 } else {
280                         int reason = (int)STTD_ERROR_OPERATION_FAILED;
281
282                         if (0 != sttdc_send_error_signal(uid, reason, "Fail to get recognition result from engine")) {
283                                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to send error info. Remove client data"); 
284
285                                 /* clean client data */
286                                 sttd_client_delete(uid);
287                         }
288
289                         dbus_message_unref(msg);
290                         SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Result from engine is NULL(%d)", i);
291                         return STTD_ERROR_OPERATION_FAILED;
292                 }
293         }
294
295         dbus_message_set_no_reply(msg, TRUE);
296
297         if (!dbus_connection_send(g_conn_sender, msg, NULL)) {
298                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to send message : Out Of Memory !");
299         }
300
301         dbus_connection_flush(g_conn_sender);
302         dbus_message_unref(msg);
303
304         return 0;
305 }
306
307 int sttdc_send_error_signal(int uid, int reason, const char *err_msg)
308 {
309         if (NULL == err_msg) {
310                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Input parameter is NULL"); 
311                 return STTD_ERROR_INVALID_PARAMETER;
312         }
313
314         int pid = sttd_client_get_pid(uid);
315         if (0 > pid) {
316                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid" );
317                 return STTD_ERROR_INVALID_PARAMETER;
318         }
319
320         char service_name[64];
321         memset(service_name, 0, 64);
322         snprintf(service_name, 64, "%s", STT_CLIENT_SERVICE_NAME);
323
324         char target_if_name[128];
325         snprintf(target_if_name, sizeof(target_if_name), "%s", STT_CLIENT_SERVICE_INTERFACE);
326
327         DBusMessage* msg = NULL;
328         msg = dbus_message_new_method_call(
329                 service_name, 
330                 STT_CLIENT_SERVICE_OBJECT_PATH, 
331                 target_if_name, 
332                 STTD_METHOD_ERROR);
333
334         if (NULL == msg) {
335                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message");
336                 return STTD_ERROR_OUT_OF_MEMORY;
337         }
338
339         dbus_message_append_args(msg, 
340                 DBUS_TYPE_INT32, &uid, 
341                 DBUS_TYPE_INT32, &reason, 
342                 DBUS_TYPE_STRING, &err_msg,
343                 DBUS_TYPE_INVALID);
344
345         if (!dbus_connection_send(g_conn_sender, msg, NULL)) {
346                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] <<<< error message : Out Of Memory !");
347         } else {
348                 SLOG(LOG_DEBUG, TAG_STTD, "<<<< Send error message : uid(%d), reason(%d), err_msg(%s)", uid, reason, err_msg);
349                 dbus_connection_flush(g_conn_sender);
350         }
351
352         dbus_message_unref(msg);
353
354         return 0;
355 }
356
357 static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler)
358 {
359         if (NULL == g_conn_listener)    return ECORE_CALLBACK_RENEW;
360
361         dbus_connection_read_write_dispatch(g_conn_listener, 50);
362
363         DBusMessage* msg = NULL;
364         msg = dbus_connection_pop_message(g_conn_listener);
365
366         if (true != dbus_connection_get_is_connected(g_conn_listener)) {
367                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Connection is disconnected");
368                 return ECORE_CALLBACK_RENEW;
369         }
370
371         /* loop again if we haven't read a message */
372         if (NULL == msg) { 
373                 return ECORE_CALLBACK_RENEW;
374         }
375
376         /* client event */
377         if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_HELLO))
378                 sttd_dbus_server_hello(g_conn_listener, msg);
379
380         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_INITIALIZE))
381                 sttd_dbus_server_initialize(g_conn_listener, msg);
382
383         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_FINALIZE))
384                 sttd_dbus_server_finalize(g_conn_listener, msg);
385
386         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_SET_CURRENT_ENGINE))
387                 sttd_dbus_server_set_current_engine(g_conn_listener, msg);
388
389         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_CHECK_APP_AGREED))
390                 sttd_dbus_server_check_app_agreed(g_conn_listener, msg);
391
392         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_GET_SUPPORT_LANGS))
393                 sttd_dbus_server_get_support_lang(g_conn_listener, msg);
394
395         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_GET_CURRENT_LANG))
396                 sttd_dbus_server_get_default_lang(g_conn_listener, msg);
397
398         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_IS_TYPE_SUPPORTED))
399                 sttd_dbus_server_is_recognition_type_supported(g_conn_listener, msg);
400
401
402         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_SET_START_SOUND))
403                 sttd_dbus_server_set_start_sound(g_conn_listener, msg);
404
405         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_UNSET_START_SOUND))
406                 sttd_dbus_server_unset_start_sound(g_conn_listener, msg);
407
408         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_SET_STOP_SOUND))
409                 sttd_dbus_server_set_stop_sound(g_conn_listener, msg);
410
411         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_UNSET_STOP_SOUND))
412                 sttd_dbus_server_unset_stop_sound(g_conn_listener, msg);
413
414
415         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_START))
416                 sttd_dbus_server_start(g_conn_listener, msg);
417
418         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_STOP))
419                 sttd_dbus_server_stop(g_conn_listener, msg);
420
421         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_CANCEL))
422                 sttd_dbus_server_cancel(g_conn_listener, msg);
423
424
425         /* free the message */
426         dbus_message_unref(msg);
427
428         return ECORE_CALLBACK_RENEW;
429 }
430
431 int sttd_dbus_open_connection()
432 {
433         DBusError err;
434         dbus_error_init(&err);
435
436         int ret;
437
438         /* Create connection for sender */
439         g_conn_sender = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
440         if (dbus_error_is_set(&err)) {
441                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail dbus_bus_get : %s", err.message);
442                 dbus_error_free(&err);
443         }
444
445         if (NULL == g_conn_sender) {
446                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to get dbus connection sender");
447                 return STTD_ERROR_OPERATION_FAILED;
448         }
449
450         /* connect to the bus and check for errors */
451         g_conn_listener = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
452
453         if (dbus_error_is_set(&err)) { 
454                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail dbus_bus_get : %s", err.message);
455                 dbus_error_free(&err); 
456         }
457
458         if (NULL == g_conn_listener) { 
459                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to get dbus connection" );
460                 return STTD_ERROR_OPERATION_FAILED;
461         }
462
463         /* request our name on the bus and check for errors */
464         ret = dbus_bus_request_name(g_conn_listener, STT_SERVER_SERVICE_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
465
466         if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
467                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to be primary owner");
468                 return STTD_ERROR_OPERATION_FAILED;
469         }
470
471         if (dbus_error_is_set(&err)) { 
472                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] dbus_bus_request_name() : %s", err.message);
473                 dbus_error_free(&err);
474                 return STTD_ERROR_OPERATION_FAILED;
475         }
476
477         /* add a rule for getting signal */
478         char rule[128];
479         snprintf(rule, 128, "type='signal',interface='%s'", STT_SERVER_SERVICE_INTERFACE);
480
481         /* add a rule for which messages we want to see */
482         dbus_bus_add_match(g_conn_listener, rule, &err); /* see signals from the given interface */
483         dbus_connection_flush(g_conn_listener);
484
485         if (dbus_error_is_set(&err)) { 
486                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] dbus_bus_add_match() : %s", err.message);
487                 return STTD_ERROR_OPERATION_FAILED;
488         }
489
490         int fd = 0;
491         dbus_connection_get_unix_fd(g_conn_listener, &fd);
492
493         g_dbus_fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)listener_event_callback, g_conn_listener, NULL, NULL);
494         if (NULL == g_dbus_fd_handler) {
495                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to get fd handler");
496                 return STTD_ERROR_OPERATION_FAILED;
497         }
498
499         return 0;
500 }
501
502 int sttd_dbus_close_connection()
503 {
504         DBusError err;
505         dbus_error_init(&err);
506
507         if (NULL != g_dbus_fd_handler) {
508                 ecore_main_fd_handler_del(g_dbus_fd_handler);
509                 g_dbus_fd_handler = NULL;
510         }
511
512         dbus_bus_release_name(g_conn_listener, STT_SERVER_SERVICE_NAME, &err);
513
514         if (dbus_error_is_set(&err)) {
515                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] dbus_bus_release_name() : %s", err.message);
516                 dbus_error_free(&err);
517         }
518
519         g_conn_listener = NULL;
520         g_conn_sender = NULL;
521
522         return 0;
523 }