2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <stdint.h> /* for uint8_t etc */
23 #include <json-glib/json-glib.h>
31 #include "icd-ioty-repr.h"
33 #include "icd-ioty-ocprocess.h"
35 GHashTable *icd_worker_table;
37 GMutex icd_csdk_mutex;
39 void icd_ioty_csdk_lock()
41 g_mutex_lock(&icd_csdk_mutex);
45 void icd_ioty_csdk_unlock()
47 g_mutex_unlock(&icd_csdk_mutex);
51 GThread* icd_ioty_init(const char *addr, unsigned short port)
57 OCStackResult result = OCInit(addr, port, OC_CLIENT_SERVER);
58 if (OC_STACK_OK != result) {
59 ERR("OCInit() Fail(%d)", result);
63 DBG("OCInit() Success");
65 thread = g_thread_try_new("packet_receive_thread", icd_ioty_ocprocess_thread,
68 ERR("g_thread_try_new() Fail(%s)", error->message);
76 void icd_ioty_deinit(GThread *thread)
80 icd_ioty_ocprocess_stop();
81 g_thread_join(thread);
84 if (OC_STACK_OK != result)
85 ERR("OCStop() Fail(%d)", result);
89 OCResourceHandle icd_ioty_register_resource(const char *uri_path,
90 const char* const* res_types, int ifaces, uint8_t properties)
95 OCResourceHandle handle;
96 const char *resInterface = NULL;
98 if (IOTCON_INTERFACE_DEFAULT & ifaces) {
99 resInterface = IC_INTERFACE_DEFAULT;
100 ifaces ^= IOTCON_INTERFACE_DEFAULT;
101 } else if (IOTCON_INTERFACE_LINK & ifaces) {
102 resInterface = IC_INTERFACE_LINK;
103 ifaces ^= IOTCON_INTERFACE_LINK;
104 } else if (IOTCON_INTERFACE_BATCH & ifaces) {
105 resInterface = IC_INTERFACE_BATCH;
106 ifaces ^= IOTCON_INTERFACE_BATCH;
107 } else if (IOTCON_INTERFACE_GROUP & ifaces) {
108 resInterface = IC_INTERFACE_GROUP;
109 ifaces ^= IOTCON_INTERFACE_GROUP;
111 ERR("Invalid interface type(%d)", ifaces);
115 icd_ioty_csdk_lock();
116 ret = OCCreateResource(&handle, res_types[0], resInterface, uri_path, EntityHandlerWrapper,
118 icd_ioty_csdk_unlock();
119 if (OC_STACK_OK != ret) {
120 ERR("OCCreateResource() Fail(%d)", ret);
124 for (i = 1; res_types[i]; i++)
125 icd_ioty_bind_type(handle, res_types[i]);
127 if (IOTCON_INTERFACE_DEFAULT & ifaces)
128 icd_ioty_bind_interface(handle, IOTCON_INTERFACE_DEFAULT);
129 if (IOTCON_INTERFACE_LINK & ifaces)
130 icd_ioty_bind_interface(handle, IOTCON_INTERFACE_LINK);
131 if (IOTCON_INTERFACE_BATCH & ifaces)
132 icd_ioty_bind_interface(handle, IOTCON_INTERFACE_BATCH);
133 if (IOTCON_INTERFACE_GROUP & ifaces)
134 icd_ioty_bind_interface(handle, IOTCON_INTERFACE_GROUP);
140 int icd_ioty_unregister_resource(OCResourceHandle resource_handle)
142 // TODO : To be implemented
143 return IOTCON_ERROR_NONE;
147 static int _ioty_convert_interface_flag(iotcon_interface_e src, const char **dest)
150 case IOTCON_INTERFACE_DEFAULT:
151 *dest = IC_INTERFACE_DEFAULT;
153 case IOTCON_INTERFACE_LINK:
154 *dest = IC_INTERFACE_LINK;
156 case IOTCON_INTERFACE_BATCH:
157 *dest = IC_INTERFACE_BATCH;
159 case IOTCON_INTERFACE_GROUP:
160 *dest = IC_INTERFACE_GROUP;
162 case IOTCON_INTERFACE_NONE:
164 ERR("Invalid interface(%d)", src);
165 return IOTCON_ERROR_INVALID_PARAMETER;
167 return IOTCON_ERROR_NONE;
171 int icd_ioty_bind_interface(OCResourceHandle resourceHandle, iotcon_interface_e iface)
174 OCStackResult result;
175 const char *resource_interface;
177 ret = _ioty_convert_interface_flag(iface, &resource_interface);
178 if (IOTCON_ERROR_NONE != ret) {
179 ERR("_ioty_convert_interface_flag(%d) Fail(%d)", iface, ret);
183 result = OCBindResourceInterfaceToResource(resourceHandle, resource_interface);
184 if (OC_STACK_OK != result) {
185 ERR("OCBindResourceInterfaceToResource() Fail(%d)", result);
186 return IOTCON_ERROR_IOTIVITY;
189 return IOTCON_ERROR_NONE;
192 int icd_ioty_bind_type(OCResourceHandle resource_handle, const char *resource_type)
196 ret = OCBindResourceTypeToResource(resource_handle, resource_type);
197 if (OC_STACK_OK != ret) {
198 ERR("OCBindResourceTypeToResource() Fail(%d)", ret);
199 return IOTCON_ERROR_IOTIVITY;
202 return IOTCON_ERROR_NONE;
206 int icd_ioty_bind_resource(OCResourceHandle parent, OCResourceHandle child)
208 // TODO : To be implemented
209 return IOTCON_ERROR_NONE;
213 int icd_ioty_unbind_resource(OCResourceHandle parent, OCResourceHandle child)
215 // TODO : To be implemented
216 return IOTCON_ERROR_NONE;
220 int icd_ioty_notify_list_of_observers(int resHandle, GVariant *msg, GVariant *observers)
222 // TODO : To be implemented
223 return IOTCON_ERROR_NONE;
227 int icd_ioty_notify_all(int resHandle)
229 // TODO : To be implemented
230 return IOTCON_ERROR_NONE;
234 int icd_ioty_send_response(GVariant *resp)
236 // TODO : To be implemented
237 return IOTCON_ERROR_NONE;
241 void _ioty_free_signal_context(void *data)
243 icd_sig_ctx_s *context = data;
244 free(context->sender);
248 int icd_ioty_find_resource(const char *host_address, const char *resource_type,
249 unsigned int signum, const char *sender)
252 OCStackResult result;
253 OCCallbackData cbdata = {0};
254 icd_sig_ctx_s *context;
255 char uri[PATH_MAX] = {0};
256 iotcon_connectivity_type_e conn_type = IOTCON_CONNECTIVITY_IPV4;
258 if (IC_STR_EQUAL == strcmp(IOTCON_MULTICAST_ADDRESS, host_address)) {
259 len = snprintf(uri, sizeof(uri), "%s", OC_MULTICAST_DISCOVERY_URI);
260 conn_type = IOTCON_CONNECTIVITY_ALL;
262 len = snprintf(uri, sizeof(uri), ICD_IOTY_COAP"%s%s", host_address,
263 OC_MULTICAST_DISCOVERY_URI);
265 if (len <= 0 || sizeof(uri) <= len) {
266 ERR("snprintf() Fail(%d)", len);
267 return IOTCON_ERROR_UNKNOWN;
270 if (IC_STR_EQUAL != strcmp(IC_STR_NULL, resource_type))
271 snprintf(uri + len, sizeof(uri), "?rt=%s", resource_type);
273 context = calloc(1, sizeof(icd_sig_ctx_s));
274 if (NULL == context) {
275 ERR("calloc() Fail(%d)", errno);
276 return IOTCON_ERROR_OUT_OF_MEMORY;
279 context->sender = ic_utils_strdup(sender);
280 context->signum = signum;
282 cbdata.context = context;
283 cbdata.cb = icd_ioty_ocprocess_find_cb;
284 cbdata.cd = _ioty_free_signal_context;
286 icd_ioty_csdk_lock();
287 result = OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL, conn_type, OC_LOW_QOS,
289 icd_ioty_csdk_unlock();
291 if (OC_STACK_OK != result) {
292 ERR("OCDoResource() Fail(%d)", result);
293 free(context->sender);
295 return IOTCON_ERROR_IOTIVITY;
298 return IOTCON_ERROR_NONE;
302 static int _ioty_get_header_options(GVariantIter *src, int src_size,
303 OCHeaderOption dest[], int dest_size)
307 unsigned short option_id;
309 RETV_IF(NULL == dest, IOTCON_ERROR_INVALID_PARAMETER);
311 if (dest_size < src_size) {
312 ERR("Exceed Size(%d)", src_size);
313 return IOTCON_ERROR_INVALID_PARAMETER;
316 while (g_variant_iter_loop(src, "(q&s)", &option_id, &option_data)) {
317 dest[i].protocolID = OC_COAP_ID;
318 dest[i].optionID = option_id;
319 dest[i].optionLength = strlen(option_data)+1;
320 memcpy(dest[i].optionData, option_data, dest[i].optionLength);
323 return IOTCON_ERROR_NONE;
327 * returned string SHOULD be released by you
329 static char* _icd_ioty_resource_generate_uri(char *host, char *uri_path, GVariant *query)
332 bool loop_first = true;
334 GVariantIter *queryIter;
335 char uri_buf[PATH_MAX] = {0};
337 len = snprintf(uri_buf, sizeof(uri_buf), "%s%s", host, uri_path);
339 ERR("snprintf() Fail");
343 /* remove suffix '/' */
344 if ('/' == uri_buf[strlen(uri_buf) - 1]) {
345 uri_buf[strlen(uri_buf) - 1] = '\0';
349 g_variant_get(query, "a(ss)", &queryIter);
351 while (g_variant_iter_loop(queryIter, "(&s&s)", &key, &value)) {
354 DBG("query exist. key(%s), value(%s)", key, value);
356 if (true == loop_first) {
357 query_len = snprintf(uri_buf + len, sizeof(uri_buf), "?%s=%s", key, value);
360 query_len = snprintf(uri_buf + len, sizeof(uri_buf), "&%s=%s", key, value);
364 ERR("snprintf() Fail");
365 g_variant_iter_free(queryIter);
371 g_variant_iter_free(queryIter);
373 return strdup(uri_buf);
377 int icd_ioty_get(GVariant *resource, GVariant *query, unsigned int signal_number,
381 int conn_type, options_size;
382 char *uri_path, *host, *uri;
383 OCStackResult result;
384 GVariantIter *options;
385 OCCallbackData cbdata = {0};
386 icd_sig_ctx_s *context;
387 int is_observable, ifaces, observe_handle;
388 OCHeaderOption oic_options[MAX_HEADER_OPTIONS];
390 g_variant_get(resource, "(&s&sba(qs)iii)", &uri_path, &host, &is_observable, &options,
391 &ifaces, &observe_handle, &conn_type);
393 uri = _icd_ioty_resource_generate_uri(host, uri_path, query);
395 ERR("_icd_ioty_resource_generate_uri() Fail");
396 g_variant_iter_free(options);
397 return IOTCON_ERROR_INVALID_PARAMETER;
400 context = calloc(1, sizeof(icd_sig_ctx_s));
401 if (NULL == context) {
402 ERR("calloc() Fail(%d)", errno);
403 g_variant_iter_free(options);
404 return IOTCON_ERROR_OUT_OF_MEMORY;
406 context->sender = ic_utils_strdup(sender);
407 context->signum = signal_number;
409 cbdata.context = context;
410 cbdata.cb = icd_ioty_ocprocess_get_cb;
411 cbdata.cd = _ioty_free_signal_context;
413 options_size = g_variant_iter_n_children(options);
414 if (0 != options_size) {
415 int ret = _ioty_get_header_options(options, options_size, oic_options,
416 sizeof(oic_options) / sizeof(oic_options[0]));
417 if (IOTCON_ERROR_NONE != ret) {
418 ERR("_ioty_get_header_options() Fail(%d)", ret);
419 free(context->sender);
422 g_variant_iter_free(options);
426 g_variant_iter_free(options);
428 icd_ioty_csdk_lock();
429 /* TODO : QoS is come from lib. And user can set QoS to client structure. */
430 result = OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL, conn_type, OC_HIGH_QOS,
431 &cbdata, options_size?oic_options:NULL, options_size);
432 icd_ioty_csdk_unlock();
436 if (OC_STACK_OK != result) {
437 ERR("OCDoResource() Fail(%d)", result);
438 free(context->sender);
440 return IOTCON_ERROR_IOTIVITY;
443 return IOTCON_ERROR_NONE;
447 int icd_ioty_put(GVariant *resource, const char *repr, GVariant *query,
448 unsigned int signal_number, const char *sender)
450 // TODO : To be implemented
451 return IOTCON_ERROR_NONE;
455 int icd_ioty_post(GVariant *resource, const char *repr, GVariant *query,
456 unsigned int signal_number, const char *sender)
458 // TODO : To be implemented
459 return IOTCON_ERROR_NONE;
463 int icd_ioty_delete(GVariant *resource, unsigned int signal_number,
466 // TODO : To be implemented
467 return IOTCON_ERROR_NONE;
471 int icd_ioty_observer_start(GVariant *resource, int observe_type,
472 GVariant *query, unsigned int signal_number, const char *sender, int *observe_h)
474 // TODO : To be implemented
475 return IOTCON_ERROR_NONE;
479 int icd_ioty_observer_stop(void *observe_h)
481 // TODO : To be implemented
482 return IOTCON_ERROR_NONE;
486 #ifdef DEVICE_INFO_IMPL /* not implemented in iotivity 0.9.1 */
487 int icd_ioty_register_device_info(GVariant *value)
489 // TODO : To be implemented
490 return IOTCON_ERROR_NONE;
494 int icd_ioty_get_device_info(const char *host_address,
495 unsigned int signal_number, const char *sender)
497 // TODO : To be implemented
498 return IOTCON_ERROR_NONE;
503 int icd_ioty_register_platform_info(GVariant *value)
505 // TODO : To be implemented
506 return IOTCON_ERROR_NONE;
510 int icd_ioty_get_platform_info(const char *host_address, unsigned int signal_number,
513 // TODO : To be implemented
514 return IOTCON_ERROR_NONE;
518 iotcon_presence_h icd_ioty_subscribe_presence(const char *host_address,
519 const char *resource_type, unsigned int signal_number, const char *sender)
521 // TODO : To be implemented
526 int icd_ioty_unsubscribe_presence(iotcon_presence_h presence_handle)
528 // TODO : To be implemented
529 return IOTCON_ERROR_NONE;
533 int icd_ioty_start_presence(unsigned int time_to_live)
535 // TODO : To be implemented
536 return IOTCON_ERROR_NONE;
540 int icd_ioty_stop_presence()
542 // TODO : To be implemented
543 return IOTCON_ERROR_NONE;