Revert "Merge plugin improvement commit"
[sdk/target/sdbd.git] / src / plugin.c
1 /*
2  * Copyright (c) 2011 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 #include <string.h>
18 #include <dlfcn.h>
19
20 #define TRACE_TAG TRACE_SDB
21 #include "log.h"
22
23 #include "sdb.h"
24
25 #include "hashtable.h"
26 #include "parameter.h"
27 #include "plugin.h"
28 #include "sdbd_plugin.h"
29
30 static void* plugin_handle = NULL;
31
32 PLUGIN_INIT plugin_init_proc = NULL;
33 PLUGIN_SYNCHRONOUS_CMD_PROC plugin_sync_proc = NULL;
34 PLUGIN_ASYNCHRONOUS_CMD_PROC plugin_async_proc = NULL;
35
36 hashtable* plugin_cmd_hashtable = NULL;
37
38 typedef struct _async_parameter {
39     int cmd;
40     parameters* in;
41     int out_fd;
42 } async_parameter;
43
44 // handler of event to be detected by plugin
45 int plugin_event_handler ( int event_type, parameters* data )
46 {
47     // TODO : implement event handler
48     if ( event_type == PLUGIN_EVENT_PWLOCK || event_type == PLUGIN_EVENT_FMMLOCK ) {
49         if ( data != NULL && data->number_of_parameter == 1 && data->array_of_parameter != NULL
50                 && data->array_of_parameter[0].type == type_int32 ) {
51
52             if ( data->array_of_parameter[0].v_int32 == PLUGIN_RET_ON ) {
53                 // locked
54                 is_pwlocked = 1;
55             } else {
56                 // unlocked
57                 is_pwlocked = 0;
58             }
59
60             send_device_status();
61
62             if ( data != NULL ) {
63                 release_parameters ( data );
64                 free ( data );
65             }
66         }
67     }
68
69     return 0;
70 }
71
72 // register commands that are supported by plugin
73 static int plugin_register_command ( int command, priority cmd_priority )
74 {
75     if ( plugin_cmd_hashtable ) {
76         int ret = hashtable_put ( plugin_cmd_hashtable, command, cmd_priority );
77         D ("register plugin command : cmd(%d), result(%d)\n", command, ret);
78     } else {
79         D ("hashtable is not created\n");
80     }
81     return 0;
82 }
83
84 // return 0 if fail to load sdbd plugin (use default plugin)
85 // return 1 if succeed to load sdbd plugin and get function pointer of plugin_init
86 static int load_plugin_not_default()
87 {
88     plugin_init_proc = NULL;
89     plugin_sync_proc = NULL;
90     plugin_async_proc = NULL;
91
92     plugin_handle = dlopen ( PLUGIN_PATH, RTLD_NOW );
93     if ( plugin_handle == NULL ) {
94         D ( "failed to dlopen(%s). error: %s\n", PLUGIN_PATH, dlerror() );
95         return 0;
96     }
97
98     plugin_init_proc = dlsym ( plugin_handle, PLUGIN_PROC_NAME_INIT );
99     if ( plugin_init_proc == NULL ) {
100         D ( "failed to get the sdbd plugin init function. error: %s\n", dlerror() );
101         dlclose ( plugin_handle );
102         plugin_handle = NULL;
103         return 0;
104     }
105
106     // if there is no implementation of plugin_sync_proc and plugin_async_proc,
107     // then use default_plugin_sync_proc and default_plugin_async_proc
108     plugin_sync_proc = dlsym ( plugin_handle, PLUGIN_PROC_NAME_SYNC_CMD );
109     if ( plugin_sync_proc == NULL ) {
110         plugin_sync_proc = default_plugin_sync_proc;
111     }
112
113     plugin_async_proc = dlsym ( plugin_handle, PLUGIN_PROC_NAME_ASYNC_CMD );
114     if ( plugin_async_proc == NULL ) {
115         plugin_async_proc = default_plugin_async_proc;
116     }
117
118     return 1;
119 }
120
121 void load_sdbd_plugin()
122 {
123     int ret;
124
125     plugin_cmd_hashtable = hashtable_create ( ht_size_31 );
126
127     ret = load_plugin_not_default();
128     if ( ret == 0 ) {
129         // use default plugin
130         plugin_init_proc = default_plugin_init;
131         plugin_sync_proc = default_plugin_sync_proc;
132         plugin_async_proc = default_plugin_async_proc;
133
134         D ( "using default plugin interface.\n" );
135     } else {
136         D ( "using sdbd plugin interface.(%s)\n", PLUGIN_PATH );
137
138         plugin_init_proc ( plugin_event_handler, plugin_register_command );
139     }
140
141     // use default plugin feature for the commands or events that are not supported by plugin
142     default_plugin_init ( plugin_event_handler, plugin_register_command );
143 }
144
145 void unload_sdbd_plugin()
146 {
147     if ( plugin_cmd_hashtable ) {
148         hashtable_destroy ( plugin_cmd_hashtable );
149         plugin_cmd_hashtable = NULL;
150     }
151
152     if ( plugin_handle ) {
153         dlclose ( plugin_handle );
154         plugin_handle = NULL;
155     }
156 }
157
158 // return 1 if plugin support given command
159 // return 0 if plugin does not support given command
160 int is_supported_by_plugin ( int cmd )
161 {
162     int ret = 0;
163
164     if ( plugin_cmd_hashtable ) {
165         int value;
166         ret = hashtable_get ( plugin_cmd_hashtable, cmd, &value );
167         D ("get from hashtable : cmd(%d), result(%d)\n", cmd, ret);
168     } else {
169         D ("hashtable is not created\n");
170     }
171
172     return ret;
173 }
174
175 static int request_sync_cmd ( int cmd, parameters* in, parameters* out )
176 {
177     int ret, pr;
178
179     out->number_of_parameter = 0;
180     out->array_of_parameter = NULL;
181
182     ret = hashtable_get ( plugin_cmd_hashtable, cmd, &pr );
183     if ( ret == 1 ) {
184         // supported by plugin
185         ret = plugin_sync_proc ( cmd, in, out );
186         if ( ret == PLUGIN_CMD_NOT_SUPPORT ) {
187             // not supported by plugin
188             ret = default_plugin_sync_proc ( cmd, in, out );
189         }
190     } else {
191         // not supported by plugin
192         ret = default_plugin_sync_proc ( cmd, in, out );
193     }
194
195     return ret;
196 }
197
198 static void request_async_cmd ( int cmd, parameters* in, int out_fd )
199 {
200     int ret, pr;
201
202     ret = hashtable_get ( plugin_cmd_hashtable, cmd, &pr );
203     if ( ret == 1 ) {
204         // supported by plugin
205         ret = plugin_async_proc ( cmd, in, out_fd );
206         if ( ret == PLUGIN_CMD_NOT_SUPPORT ) {
207             // not supported by plugin
208             ret = default_plugin_async_proc ( cmd, in, out_fd );
209         }
210     } else {
211         // not supported by plugin
212         ret = default_plugin_async_proc ( cmd, in, out_fd );
213     }
214
215     release_parameters ( in );
216     if ( in != NULL ) {
217         free( in );
218     }
219     sdb_close(out_fd);
220 }
221
222 static void *async_proc_bootstrap_func(void *x)
223 {
224     async_parameter *p = x;
225     request_async_cmd(p->cmd, p->in, p->out_fd);
226     free(p);
227     return 0;
228 }
229
230 static int create_async_proc_thread( int cmd, parameters* in )
231 {
232     async_parameter* async_param;
233     sdb_thread_t t;
234     int s[2];
235
236     if( sdb_socketpair(s) ) {
237         D("cannot create async proc socket pair\n");
238         return -1;
239     }
240
241     async_param = ( async_parameter* ) malloc(sizeof(async_parameter));
242     if( async_param == NULL ) fatal("cannot allocate async_parameter");
243     async_param->cmd = cmd;
244     async_param->in = in;
245     async_param->out_fd = s[1];
246
247     if(sdb_thread_create( &t, async_proc_bootstrap_func, async_param)){
248         free(async_param);
249         sdb_close(s[0]);
250         sdb_close(s[1]);
251         D("cannot create async proc thread\n");
252         return -1;
253     }
254
255     D("async proc thread started, %d:%d\n",s[0], s[1]);
256     return s[0];
257 }
258
259 // return 1 if succeed to get capability from plugin
260 // return 0 otherwise
261 int request_capability_to_plugin ( int cap, char* out_buf, unsigned int out_len )
262 {
263     int success = 0;
264     int ret;
265     parameters in, out;
266
267     in.number_of_parameter = 1;
268     in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
269     in.array_of_parameter[0].type = type_int32;
270     in.array_of_parameter[0].v_int32 = cap;
271
272     D ("requested capability : %d\n", cap);
273
274     ret = request_sync_cmd ( PLUGIN_SYNC_CMD_CAPABILITY, &in, &out );
275     if ( ret == PLUGIN_CMD_SUCCESS ) {
276         strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
277         out_buf[out_len - 1] = '\0';
278         success = 1;
279         release_parameters ( &out );
280
281         D ("request capability success : %s\n", out_buf);
282     }
283
284     release_parameters ( &in );
285     return success;
286 }
287
288 // return 1 if allowed by plugin (valid)
289 // return 0 if disallowed by plugin (invalid)
290 int request_validity_to_plugin ( int cmd, const char* in_buf )
291 {
292     int success = 0;
293     int ret;
294     parameters in, out;
295
296     if ( in_buf != NULL ) {
297         in.number_of_parameter = 1;
298         in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
299         in.array_of_parameter[0].type = type_string;
300         in.array_of_parameter[0].v_string.length = strlen ( in_buf );
301         in.array_of_parameter[0].v_string.data = strdup ( in_buf );
302     } else {
303         in.number_of_parameter = 0;
304         in.array_of_parameter = NULL;
305     }
306
307     D ("requested validity : %d, %s\n", cmd, in_buf);
308
309     ret = request_sync_cmd ( cmd, &in, &out );
310     if ( ret == PLUGIN_CMD_SUCCESS ) {
311         success = ( out.array_of_parameter[0].v_int32 == PLUGIN_RET_VALID ) ? 1 : 0;
312         release_parameters ( &out );
313
314         D ("request validity success : %d\n", out.array_of_parameter[0].v_int32);
315     }
316
317     release_parameters ( &in );
318     return success;
319 }
320
321 // return 1 if succeed to convert
322 // return 0 otherwise
323 int request_conversion_to_plugin ( int cmd, const char* in_buf, char* out_buf, unsigned int out_len )
324 {
325     int success = 0;
326     int ret;
327     parameters in, out;
328
329     in.number_of_parameter = 1;
330     in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
331     in.array_of_parameter[0].type = type_string;
332     in.array_of_parameter[0].v_string.length = strlen ( in_buf );
333     in.array_of_parameter[0].v_string.data = strdup ( in_buf );
334
335     ret = request_sync_cmd ( cmd, &in, &out );
336     if ( ret == PLUGIN_CMD_SUCCESS ) {
337         strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
338         out_buf[out_len - 1] = '\0';
339         success = 1;
340         release_parameters ( &out );
341     }
342
343     release_parameters ( &in );
344     return success;
345 }
346
347 // return 1 if locked
348 // return 0 if unlocked
349 // return -1 if request failed
350 int request_lock_state_to_plugin ( int lock_type )
351 {
352     int result = -1;
353     int ret;
354     parameters in, out;
355
356     in.number_of_parameter = 1;
357     in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
358     in.array_of_parameter[0].type = type_int32;
359     in.array_of_parameter[0].v_int32 = lock_type;
360
361     ret = request_sync_cmd ( PLUGIN_SYNC_CMD_GET_LOCK_STATE, &in, &out );
362     if ( ret == PLUGIN_CMD_SUCCESS ) {
363         if ( out.array_of_parameter[0].v_int32 == PLUGIN_RET_ON ) {
364             result = 1;
365         } else {
366             result = 0;
367         }
368         is_pwlocked = result;
369         release_parameters ( &out );
370     }
371
372     release_parameters ( &in );
373
374     return result;
375 }
376
377 // return nonnegative integer that is a socket descriptor for communication
378 //        with async proc thread if success to create async proc thread
379 // return -1 if failed to create async proc thread
380 int request_appcmd_to_plugin ( const char* in_buf )
381 {
382     parameters* in;
383     int fd;
384
385     in = ( parameters* ) malloc ( sizeof ( parameters ) );
386     if ( in_buf != NULL ) {
387         in->number_of_parameter = 1;
388         in->array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
389         in->array_of_parameter[0].type = type_string;
390         in->array_of_parameter[0].v_string.length = strlen ( in_buf );
391         in->array_of_parameter[0].v_string.data = strdup ( in_buf );
392     } else {
393         in->number_of_parameter = 0;
394         in->array_of_parameter = NULL;
395     }
396
397     fd = create_async_proc_thread( PLUGIN_ASYNC_CMD_APPCMD_SERVICE, in );
398
399     return fd;
400 }