Modify terms related to signal
[platform/core/iot/iotcon.git] / lib / icl-presence.c
1 /*
2  * Copyright (c) 2015 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 #include <stdio.h>
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <glib.h>
22
23 #include "iotcon.h"
24 #include "iotcon-internal.h"
25 #include "ic-utils.h"
26 #include "icl.h"
27 #include "icl-resource-types.h"
28 #include "icl-dbus.h"
29
30 #define ICL_PRESENCE_TTL_SECONDS_MAX (60 * 60 * 24) /* 60 sec/min * 60 min/hr * 24 hr/day */
31
32 typedef struct icl_presence {
33         char *host_address;
34         iotcon_connectivity_type_e connectivity_type;
35         char *resource_type;
36         iotcon_presence_cb cb;
37         void *user_data;
38         unsigned int sub_id;
39         int64_t handle;
40 } icl_presence_s;
41
42
43 typedef struct icl_presence_response {
44         char *host_address;
45         iotcon_connectivity_type_e connectivity_type;
46         char *resource_type;
47         iotcon_presence_result_e result;
48         iotcon_presence_trigger_e trigger;
49 } icl_presence_response_s;
50
51
52 API int iotcon_start_presence(unsigned int time_to_live)
53 {
54         FN_CALL;
55         int ret;
56         GError *error = NULL;
57
58         RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
59         RETV_IF(ICL_PRESENCE_TTL_SECONDS_MAX < time_to_live, IOTCON_ERROR_INVALID_PARAMETER);
60
61         ic_dbus_call_start_presence_sync(icl_dbus_get_object(), time_to_live, &ret, NULL,
62                         &error);
63         if (error) {
64                 ERR("ic_dbus_call_start_presence_sync() Fail(%s)", error->message);
65                 ret = icl_dbus_convert_dbus_error(error->code);
66                 g_error_free(error);
67                 return ret;
68         }
69
70         if (IOTCON_ERROR_NONE != ret) {
71                 ERR("iotcon-daemon Fail(%d)", ret);
72                 return icl_dbus_convert_daemon_error(ret);
73         }
74
75         return IOTCON_ERROR_NONE;
76 }
77
78
79 API int iotcon_stop_presence(void)
80 {
81         FN_CALL;
82         int ret;
83         GError *error = NULL;
84
85         RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
86
87         ic_dbus_call_stop_presence_sync(icl_dbus_get_object(), &ret, NULL, &error);
88         if (error) {
89                 ERR("ic_dbus_call_stop_presence_sync() Fail(%s)", error->message);
90                 ret = icl_dbus_convert_dbus_error(error->code);
91                 g_error_free(error);
92                 return ret;
93         }
94
95         if (IOTCON_ERROR_NONE != ret) {
96                 ERR("iotcon-daemon Fail(%d)", ret);
97                 return icl_dbus_convert_daemon_error(ret);
98         }
99
100         return IOTCON_ERROR_NONE;
101 }
102
103
104 static void _icl_presence_cb(GDBusConnection *connection,
105                 const gchar *sender_name,
106                 const gchar *object_path,
107                 const gchar *interface_name,
108                 const gchar *signal_name,
109                 GVariant *parameters,
110                 gpointer user_data)
111 {
112         FN_CALL;
113         unsigned int nonce;
114         char *host_address, *resource_type;
115         int res, connectivity_type, trigger;
116         icl_presence_s *presence = user_data;
117         iotcon_presence_cb cb = presence->cb;
118         icl_presence_response_s response = {0};
119
120         g_variant_get(parameters, "(iu&sii&s)", &res, &nonce, &host_address,
121                         &connectivity_type, &trigger, &resource_type);
122
123         if (res < IOTCON_ERROR_NONE && cb)
124                 cb(presence, icl_dbus_convert_daemon_error(res), NULL, presence->user_data);
125
126         DBG("presence nonce : %d", nonce);
127
128         response.host_address = host_address;
129         response.connectivity_type = connectivity_type;
130         response.resource_type = ic_utils_dbus_decode_str(resource_type);
131         response.result = res;
132         response.trigger = trigger;
133
134         if (cb)
135                 cb(presence, IOTCON_ERROR_NONE, &response, presence->user_data);
136 }
137
138
139 static void _icl_presence_conn_cleanup(icl_presence_s *presence)
140 {
141         presence->sub_id = 0;
142
143         if (presence->handle) {
144                 presence->handle = 0;
145                 return;
146         }
147
148         free(presence->resource_type);
149         free(presence->host_address);
150         free(presence);
151 }
152
153
154 /* The length of resource_type should be less than or equal to 61. */
155 API int iotcon_add_presence_cb(const char *host_address,
156                 iotcon_connectivity_type_e connectivity_type,
157                 const char *resource_type,
158                 iotcon_presence_cb cb,
159                 void *user_data,
160                 iotcon_presence_h *presence_handle)
161 {
162         FN_CALL;
163         int ret;
164         GError *error = NULL;
165         icl_presence_s *presence;
166         unsigned int sub_id, signal_number;
167         char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
168
169         RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_INVALID_PARAMETER);
170         RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
171         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
172
173         if (resource_type && (ICL_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type))) {
174                 ERR("The length of resource_type(%s) is invalid", resource_type);
175                 return IOTCON_ERROR_INVALID_PARAMETER;
176         }
177
178         signal_number = icl_dbus_generate_signal_number();
179
180         presence = calloc(1, sizeof(icl_presence_s));
181         if (NULL == presence) {
182                 ERR("calloc() Fail(%d)", errno);
183                 return IOTCON_ERROR_OUT_OF_MEMORY;
184         }
185
186         resource_type = ic_utils_dbus_encode_str(resource_type);
187
188         ic_dbus_call_subscribe_presence_sync(icl_dbus_get_object(),
189                         host_address,
190                         connectivity_type,
191                         resource_type,
192                         signal_number,
193                         &(presence->handle),
194                         NULL,
195                         &error);
196         if (error) {
197                 ERR("ic_dbus_call_subscribe_presence_sync() Fail(%s)", error->message);
198                 ret = icl_dbus_convert_dbus_error(error->code);
199                 g_error_free(error);
200                 free(presence);
201                 return ret;
202         }
203
204         if (0 == presence->handle) {
205                 ERR("iotcon-daemon Fail");
206                 free(presence);
207                 return IOTCON_ERROR_IOTIVITY;
208         }
209
210         snprintf(signal_name, sizeof(signal_name), "%s_%u", IC_DBUS_SIGNAL_PRESENCE,
211                         signal_number);
212
213         presence->cb = cb;
214         presence->user_data = user_data;
215
216         presence->host_address = ic_utils_strdup(host_address);
217         presence->connectivity_type = connectivity_type;
218         if (resource_type)
219                 presence->resource_type = strdup(resource_type);
220
221         sub_id = icl_dbus_subscribe_signal(signal_name, presence,
222                         _icl_presence_conn_cleanup, _icl_presence_cb);
223         if (0 == sub_id) {
224                 ERR("icl_dbus_subscribe_signal() Fail");
225                 free(presence->resource_type);
226                 free(presence->host_address);
227                 free(presence);
228                 return IOTCON_ERROR_DBUS;
229         }
230
231         presence->sub_id = sub_id;
232
233         *presence_handle = presence;
234
235         return IOTCON_ERROR_NONE;
236 }
237
238
239 API int iotcon_remove_presence_cb(iotcon_presence_h presence)
240 {
241         FN_CALL;
242         int ret;
243         GError *error = NULL;
244
245         RETV_IF(NULL == presence, IOTCON_ERROR_INVALID_PARAMETER);
246
247         if (0 == presence->sub_id) { /* disconnected iotcon dbus */
248                 WARN("Invalid Presence handle");
249                 free(presence->resource_type);
250                 free(presence->host_address);
251                 free(presence);
252                 return IOTCON_ERROR_NONE;
253         }
254
255         if (NULL == icl_dbus_get_object()) {
256                 ERR("icl_dbus_get_object() return NULL");
257                 return IOTCON_ERROR_DBUS;
258         }
259
260         ic_dbus_call_unsubscribe_presence_sync(icl_dbus_get_object(), presence->handle,
261                         &ret, NULL, &error);
262         if (error) {
263                 ERR("ic_dbus_call_unsubscribe_presence_sync() Fail(%s)", error->message);
264                 ret = icl_dbus_convert_dbus_error(error->code);
265                 g_error_free(error);
266                 return ret;
267         }
268
269         if (IOTCON_ERROR_NONE != ret) {
270                 ERR("iotcon-daemon Fail(%d)", ret);
271                 return icl_dbus_convert_daemon_error(ret);
272         }
273         presence->handle = 0;
274
275         icl_dbus_unsubscribe_signal(presence->sub_id);
276
277         return IOTCON_ERROR_NONE;
278 }
279
280
281 API int iotcon_presence_get_host_address(iotcon_presence_h presence, char **host_address)
282 {
283         RETV_IF(NULL == presence, IOTCON_ERROR_INVALID_PARAMETER);
284         RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
285
286         *host_address = presence->host_address;
287
288         return IOTCON_ERROR_NONE;
289 }
290
291
292 API int iotcon_presence_get_connectivity_type(iotcon_presence_h presence,
293                 int *connectivity_type)
294 {
295         RETV_IF(NULL == presence, IOTCON_ERROR_INVALID_PARAMETER);
296         RETV_IF(NULL == connectivity_type, IOTCON_ERROR_INVALID_PARAMETER);
297
298         *connectivity_type = presence->connectivity_type;
299
300         return IOTCON_ERROR_NONE;
301 }
302
303
304 API int iotcon_presence_get_resource_type(iotcon_presence_h presence,
305                 char **resource_type)
306 {
307         RETV_IF(NULL == presence, IOTCON_ERROR_INVALID_PARAMETER);
308         RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
309
310         *resource_type = presence->resource_type;
311
312         return IOTCON_ERROR_NONE;
313 }
314
315
316 API int iotcon_presence_response_get_host_address(iotcon_presence_response_h response,
317                 char **host_address)
318 {
319         RETV_IF(NULL == response, IOTCON_ERROR_INVALID_PARAMETER);
320         RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
321
322         *host_address = response->host_address;
323
324         return IOTCON_ERROR_NONE;
325 }
326
327
328 API int iotcon_presence_response_get_connectivity_type(
329                 iotcon_presence_response_h response, int *connectivity_type)
330 {
331         RETV_IF(NULL == response, IOTCON_ERROR_INVALID_PARAMETER);
332         RETV_IF(NULL == connectivity_type, IOTCON_ERROR_INVALID_PARAMETER);
333
334         *connectivity_type = response->connectivity_type;
335
336         return IOTCON_ERROR_NONE;
337 }
338
339
340 API int iotcon_presence_response_get_resource_type(iotcon_presence_response_h response,
341                 char **resource_type)
342 {
343         RETV_IF(NULL == response, IOTCON_ERROR_INVALID_PARAMETER);
344         RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
345
346         *resource_type = response->resource_type;
347
348         return IOTCON_ERROR_NONE;
349 }
350
351
352 API int iotcon_presence_response_get_result(iotcon_presence_response_h response,
353                 int *result)
354 {
355         RETV_IF(NULL == response, IOTCON_ERROR_INVALID_PARAMETER);
356         RETV_IF(NULL == result, IOTCON_ERROR_INVALID_PARAMETER);
357
358         *result = response->result;
359
360         return IOTCON_ERROR_NONE;
361 }
362
363
364 API int iotcon_presence_response_get_trigger(iotcon_presence_response_h response,
365                 int *trigger)
366 {
367         RETV_IF(NULL == response, IOTCON_ERROR_INVALID_PARAMETER);
368         RETV_IF(NULL == trigger, IOTCON_ERROR_INVALID_PARAMETER);
369
370         if (IOTCON_PRESENCE_OK != response->result) {
371                 ERR("trigger is valid if IOTCON_PRESENCE_OK");
372                 return IOTCON_ERROR_INVALID_PARAMETER;
373         }
374
375         *trigger = response->trigger;
376
377         return IOTCON_ERROR_NONE;
378 }
379