Add 3.0 APIs and sync APIs same as 2.4
[platform/core/convergence/service-adaptor.git] / server / sal_main.c
1 /*
2  * Service Adaptor
3  *
4  * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <glib-object.h>
22 #include <glib-unix.h>
23
24 #include <app.h>
25
26 #include "service_adaptor_internal.h"
27
28 #include "sal.h"
29 #include "sal_auth.h"
30 #include "sal_contact.h"
31 #include "sal_storage.h"
32 #include "sal_resource.h"
33 #include "sal_observer.h"
34 #include "sal_ipc_server.h"
35 #include "sal_service_provider.h"
36
37 #include "service_discovery.h"
38 #include "service_federation.h"
39
40 //******************************************************************************
41 //* Global variables and defines
42 //******************************************************************************
43 #define FILE_PATH_LEN   256
44
45 static sal_h g_service_adaptor = NULL;
46
47 //******************************************************************************
48 //* Private interface
49 //******************************************************************************
50
51 //******************************************************************************
52 //* Private interface definition
53 //******************************************************************************
54
55 /**
56  * @brief callback of app control
57  *
58  * @return      void.
59  */
60 static bool _app_control_extra_data_cb(app_control_h app_control, const char *key, void *user_data)
61 {
62         char *value = NULL;
63
64         app_control_get_extra_data(app_control, key, &value);
65         SAL_INFO("PLUGIN Key (%s): %s", key, value);
66
67         g_hash_table_insert((GHashTable *) user_data, (char *) key, value);
68
69         return true;
70 }
71
72 /**
73  * @brief callback of plugin connection
74  *
75  * @return      void.
76  */
77 static void _provider_connect_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data)
78 {
79         SAL_FN_CALL;
80
81         RET_IF(APP_CONTROL_RESULT_FAILED == result);
82
83         sal_h sal = sal_get_handle();
84         RETM_IF(NULL == sal, "sal_get_handle() Fail");
85
86         GHashTable *service = g_hash_table_new(g_str_hash, g_str_equal);
87         app_control_foreach_extra_data(reply, _app_control_extra_data_cb, (void *) service);
88
89         provider_user_data_h provider_user_data = (provider_user_data_h) user_data;
90
91         GHashTableIter iter;
92         gpointer iter_key, iter_value;
93
94         g_hash_table_iter_init(&iter, service);
95         while (g_hash_table_iter_next(&iter, &iter_key, &iter_value))
96         {
97                 if (0 == strcmp(iter_key, PLUGIN_KEY_AUTH))
98                 {
99                         auth_plugin_h plugin = NULL;
100                         auth_adaptor_create_plugin(provider_user_data->uri, provider_user_data->name, provider_user_data->package, &plugin);
101                         auth_adaptor_register_plugin_service(plugin, service);
102                         auth_adaptor_add_plugin(sal->auth, plugin);
103                 }
104                 else if (0 == strcmp(iter_key, PLUGIN_KEY_STORAGE))
105                 {
106                         storage_plugin_h plugin = NULL;
107                         storage_adaptor_create_plugin(provider_user_data->uri, provider_user_data->name, provider_user_data->package, &plugin);
108                         storage_adaptor_register_plugin_service(plugin, service);
109                         storage_adaptor_add_plugin(sal->storage, plugin);
110                 }
111         }
112
113         g_hash_table_destroy(service);
114
115         SAL_FN_END;
116 }
117
118 /**
119  * @brief callback of plugin disconnection
120  *
121  * @return      void.
122  */
123 static void _provider_disconnect_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data)
124 {
125         SAL_FN_CALL;
126
127         RET_IF(APP_CONTROL_RESULT_FAILED == result);
128
129         sal_h sal = sal_get_handle();
130         RETM_IF(NULL == sal, "sal_get_handle() Fail");
131
132         char *uri = (char *) user_data;
133
134         auth_plugin_h plugin = auth_adaptor_get_plugin(sal->auth, uri);
135         auth_adaptor_remove_plugin(sal->auth, plugin);
136         auth_adaptor_unregister_plugin_service(plugin);
137         auth_adaptor_destroy_plugin(plugin);
138
139         // TODO: destroy plugin of other adaptor
140
141         SAL_FN_END;
142 }
143
144 /**
145  * @brief create spec file
146  *
147  * @return      void.
148  */
149 static service_adaptor_error_e _sal_create_spec_file(sal_h sal)
150 {
151         SAL_FN_CALL;
152
153         int ret = 0;
154         RETV_IF(NULL == sal, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
155
156         return ret;
157 }
158
159 /**
160  * @brief destroy spec file
161  *
162  * @return      void.
163  */
164 static service_adaptor_error_e _sal_destroy_spec_file(sal_h sal)
165 {
166         SAL_FN_CALL;
167
168         int ret = 0;
169         RETV_IF(NULL == sal, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
170
171         return ret;
172 }
173
174 /**
175  * @brief start service adaptor
176  *
177  * @return      void.
178  */
179 static service_adaptor_error_e _sal_start(sal_h sal)
180 {
181         SAL_FN_CALL;
182
183         int ret = 0;
184         RETV_IF(NULL == sal, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
185
186         ret = auth_adaptor_start(sal->auth);
187         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_INTERNAL, "auth_adaptor_start() Fail(%d)", ret);
188
189         ret = contact_adaptor_start(sal->contact);
190         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_INTERNAL, "contact_adaptor_start() Fail(%d)", ret);
191
192         ret = storage_adaptor_start(sal->storage);
193         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_INTERNAL, "storage_adaptor_start() Fail(%d)", ret);
194
195         ret = resource_adaptor_start(sal->resource);
196         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_INTERNAL, "resource_adaptor_start() Fail(%d)", ret);
197
198         ret = sal_observer_register_existed_plugin();
199         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, ret, "sal_observer_register_existed_plugin() Fail(%d)", ret);
200
201         g_mutex_lock(&sal->mutex);
202         sal->start = sal->start + 1;
203         g_cond_signal(&sal->cond);
204         g_mutex_unlock(&sal->mutex);
205
206         return ret;
207 }
208
209 /**
210  * @brief stop service adaptor
211  *
212  * @return      void.
213  */
214 static service_adaptor_error_e _sal_stop(sal_h sal)
215 {
216         SAL_FN_CALL;
217
218         int ret = 0;
219         RETV_IF(NULL == sal, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
220         RETVM_IF(0 == sal->start, SERVICE_ADAPTOR_ERROR_INTERNAL, "could not start service adaptor");
221
222         ret += auth_adaptor_stop(sal->auth);
223         ret += contact_adaptor_stop(sal->contact);
224         ret += storage_adaptor_stop(sal->storage);
225         ret += resource_adaptor_stop(sal->resource);
226         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_INTERNAL, "could not stop service adaptor(%d)", ret);
227
228         sal->start = 0;
229
230         return ret;
231 }
232
233 /**
234  * @brief create service adaptor
235  *
236  * @return      void.
237  */
238 static sal_h _sal_create()
239 {
240         SAL_FN_CALL;
241
242         sal_h sal = NULL;
243
244         // 1) create auth adaptor handle
245         auth_adaptor_h auth = auth_adaptor_create();
246         TRYM_IF(NULL == auth, "sal_auth_create_handle() Fail");
247
248         // 2) create contact adaptor handle
249         contact_adaptor_h contact = contact_adaptor_create();
250         TRYM_IF(NULL == contact, "sal_contact_create_handle() Fail");
251
252         // 3) create storage adaptor handle
253         storage_adaptor_h storage = storage_adaptor_create();
254         TRYM_IF(NULL == storage, "sal_storage_create_handle() Fail");
255
256         // 4) create resource adaptor handle
257         resource_adaptor_h resource = resource_adaptor_create();
258         TRYM_IF(NULL == resource, "sal_resource_create_handle() Fail");
259
260         // 5) register auth adaptor listener
261         auth_adaptor_listener_h auth_listener = sal_auth_register_listener(auth);
262         TRYM_IF(NULL == auth_listener, "sal_auth_register_listener() Fail");
263
264         // 6) register contact adaptor listener
265         contact_adaptor_listener_h contact_listener = sal_contact_register_listener(contact);
266         TRYM_IF(NULL == contact_listener, "sal_contact_register_listener() Fail");
267
268         // 7) register storage adaptor listener
269         storage_adaptor_listener_h storage_listener = sal_storage_register_listener(storage);
270         TRYM_IF(NULL == storage_listener, "sal_storage_register_listener() Fail");
271
272         // 8) register resource adaptor listener
273         resource_adaptor_listener_h resource_listener = sal_resource_register_listener(resource);
274         TRYM_IF(NULL == resource_listener, "sal_resource_register_listener() Fail");
275
276         // 9) create service adaptor
277         sal = (sal_h) g_malloc0(sizeof(sal_s));
278         TRYM_IF(NULL == sal, "could not create service adaptor");
279
280         sal->auth = auth;
281         sal->contact = contact;
282         sal->storage = storage;
283         sal->resource = resource;
284
285         g_mutex_init(&sal->mutex);
286         g_cond_init(&sal->cond);
287
288 catch:
289         // TODO: free
290
291         return sal;
292 }
293
294 /**
295  * @brief destroy service adaptor
296  *
297  * @return      void.
298  */
299 static void _sal_destroy(sal_h sal)
300 {
301         SAL_FN_CALL;
302
303         RET_IF(NULL == sal);
304
305         // 1) destroy service list
306         if (NULL != sal->svc_list)
307         {
308                 g_list_free(sal->svc_list);
309                 sal->svc_list = NULL;
310         }
311
312         // 2) free service adaptor handle
313         SAL_FREE(sal);
314
315         SAL_FN_END;
316 }
317
318 /**
319  * @brief init service adaptor
320  *
321  * @return      void.
322  */
323 static service_adaptor_error_e _sal_init()
324 {
325         SAL_FN_CALL;
326         int ret = SERVICE_ADAPTOR_ERROR_NONE;
327
328         // 1) create adaptor (memory allocation)
329         sal_h sal = _sal_create();
330         RETVM_IF(NULL == sal, SERVICE_ADAPTOR_ERROR_INTERNAL, "_sal_create() Fail");
331
332         // 2) start adaptor (plugin loading)
333         ret = _sal_start(sal);
334         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_INTERNAL, "_sal_start() Fail(%d)", ret);
335
336         // 3) start adaptor (spec file creation)
337         ret = _sal_create_spec_file(sal);
338         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_INTERNAL, "_sal_create_spec_file() Fail(%d)", ret);
339
340         // 4) init dbus server
341         ret = sal_ipc_server_init();
342         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_IPC_UNSTABLE, "sal_ipc_server_init() Fail(%d)", ret);
343
344         // 5) assign to global service adaptor handle
345         g_service_adaptor = sal;
346
347         // 6) register callback for package event
348         ret = sal_observer_start();
349         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, ret, "sal_observer_start() Fail(%d)", ret);
350
351         // 7) create service discovery
352         ret = service_discovery_create();
353         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, ret, "service_discovery_create() Fail(%d)", ret);
354
355         // 8) create service federation
356         ret = service_federation_create();
357         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, ret, "service_federation_create() Fail(%d)", ret);
358
359         return ret;
360 }
361
362 /**
363  * @brief deinit service adaptor
364  *
365  * @param[in]   service_adaptor         specifies handle of service adaptor
366  * @return      void.
367  */
368 static void _sal_deinit(sal_h sal)
369 {
370         SAL_FN_CALL;
371
372         RET_IF(NULL == sal);
373
374         sal_ipc_server_deinit();
375
376         _sal_destroy_spec_file(sal);
377
378         if (0 < sal->start)
379         {
380                 _sal_stop(sal);
381         }
382
383         _sal_destroy(sal);
384
385         SAL_FN_END;
386 }
387
388 /**
389  * @brief main signal function
390  *
391  * @param[in]   data            specifies user data passed by main function
392  * @return      void.
393  */
394 static gint _sigterm_callback(void *data)
395 {
396         g_main_loop_quit((GMainLoop*)data);
397
398         return 0;
399 }
400
401 /**
402  * @brief main function
403  *
404  * @param[in]   argc            specifies count of arguments
405  * @param[in]   argv            specifies value list of arguments
406  * @return      void.
407  */
408 int main(int argc, char *argv[])
409 {
410         int ret = SERVICE_ADAPTOR_ERROR_NONE;
411         GMainLoop *loop = NULL;
412
413 #if !GLIB_CHECK_VERSION(2,32,0)
414         g_thread_init(NULL);
415 #endif
416 #if !GLIB_CHECK_VERSION(2,35,0)
417         g_type_init();
418 #endif
419
420         ret = _sal_init();
421         RETVM_IF(SERVICE_ADAPTOR_ERROR_NONE != ret, 0, "_sal_init() Fail(%d)", ret);
422
423         // mainloop of main thread
424         loop = g_main_loop_new(NULL, FALSE);
425
426         // installing signal handlers
427         g_unix_signal_add_full(G_PRIORITY_HIGH, SIGINT,
428                         _sigterm_callback, loop, NULL );
429         g_unix_signal_add_full(G_PRIORITY_HIGH, SIGTERM,
430                         _sigterm_callback, loop, NULL );
431
432         // start application's main loop
433         g_main_loop_run(loop);
434
435         // cleanup after mainloop
436         g_main_loop_unref(loop);
437
438         sal_h sal = sal_get_handle();
439         _sal_deinit(sal);
440
441         return 0;
442 }
443
444 //******************************************************************************
445 //* Public interface definition
446 //******************************************************************************
447
448 API sal_h sal_get_handle()
449 {
450         SAL_FN_CALL;
451
452         return g_service_adaptor;
453 }
454
455 API char *sal_get_root_path()
456 {
457         SAL_FN_CALL;
458
459         char *root_path = NULL;
460         char tnfs_root_path[FILE_PATH_LEN] = {0,};
461
462         // TODO: tmp -> need to use get_path APIs of TNFS
463         snprintf(tnfs_root_path, FILE_PATH_LEN, "%s", "/opt/storage/tnfs");
464         root_path = strdup(tnfs_root_path);
465
466         return root_path;
467 }
468
469 API service_adaptor_error_e sal_adaptor_connect(const char *uri)
470 {
471         SAL_FN_CALL;
472
473         RETV_IF(NULL == uri, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
474
475         SAL_INFO("uri: %s", uri);
476
477         return SERVICE_ADAPTOR_ERROR_NONE;
478 }
479
480 API service_adaptor_error_e sal_adaptor_disconnect(const char *uri)
481 {
482         SAL_FN_CALL;
483
484         RETV_IF(NULL == uri, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
485
486         SAL_INFO("uri: %s", uri);
487
488         return SERVICE_ADAPTOR_ERROR_NONE;
489 }
490
491 API service_adaptor_error_e sal_adaptor_get_plugins(char ***plugins, int *plugins_size)
492 {
493         SAL_FN_CALL;
494
495         RETV_IF(NULL == g_service_adaptor, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
496         RETV_IF(NULL == g_service_adaptor->auth, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
497
498         int size = g_list_length(g_service_adaptor->auth->plugins);
499         RETV_IF(0 == size, SERVICE_ADAPTOR_ERROR_NO_DATA);
500
501         int i = 0;
502         char **uri = (char **) g_malloc0(sizeof(char *) * size);
503
504         for (GList *list = g_list_first(g_service_adaptor->auth->plugins); list != NULL; list = list->next)
505         {
506                 auth_plugin_h this = (auth_plugin_h) list->data;
507
508                 uri[i] = strdup(this->uri);
509         }
510
511         *plugins = uri;
512         *plugins_size = size;
513
514         return SERVICE_ADAPTOR_ERROR_NONE;
515 }
516
517 API service_adaptor_error_e sal_provider_connect(const char *uri, const char *name, const char *package)
518 {
519         SAL_FN_CALL;
520
521         RETV_IF(NULL == uri, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
522
523         app_control_h request;
524         app_control_create(&request);
525
526         app_control_set_app_id(request, uri);
527         app_control_set_operation(request, PLUGIN_CONNECT_URI);
528
529         provider_user_data_h provider_user_data = (provider_user_data_h) g_malloc0(sizeof(provider_user_data_s));
530         provider_user_data->uri = strdup(uri);
531         provider_user_data->name = strdup(name);
532         provider_user_data->package = strdup(package);
533
534         int ret = app_control_send_launch_request(request, _provider_connect_cb, provider_user_data);
535
536         RETVM_IF(APP_CONTROL_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_SYSTEM, "app_control_send_launch_request() Fail(%d)", ret);
537
538         app_control_destroy(request);
539
540         return SERVICE_ADAPTOR_ERROR_NONE;
541 }
542
543 API service_adaptor_error_e sal_provider_disconnect(const char *uri)
544 {
545         SAL_FN_CALL;
546
547         RETV_IF(NULL == uri, SERVICE_ADAPTOR_ERROR_INVALID_PARAMETER);
548
549         app_control_h request;
550         app_control_create(&request);
551
552         app_control_set_app_id(request, uri);
553         app_control_set_operation(request, PLUGIN_DISCONNECT_URI);
554
555         int ret = app_control_send_launch_request(request, _provider_disconnect_cb, (void *) uri);
556
557         RETVM_IF(APP_CONTROL_ERROR_NONE != ret, SERVICE_ADAPTOR_ERROR_SYSTEM, "app_control_send_launch_request() Fail(%d)", ret);
558
559         app_control_destroy(request);
560
561         return SERVICE_ADAPTOR_ERROR_NONE;
562 }
563
564 API char *sal_provider_get_uri(const char *package)
565 {
566         SAL_FN_CALL;
567
568         RETV_IF(NULL == package, NULL);
569
570         sal_h sal = sal_get_handle();
571         RETVM_IF(NULL == sal, NULL, "sal_get_handle() Fail");
572
573         char *uri = auth_adaptor_get_uri(sal->auth, package);
574
575         return uri;
576 }